git commit -m "first commit"

This commit is contained in:
2026-05-28 10:29:58 +07:00
commit 167c52aeb6
2048 changed files with 740251 additions and 0 deletions

13
navigations/sbpl/.gitignore vendored Executable file
View File

@@ -0,0 +1,13 @@
cmake_install.cmake
envdebug.txt
debug.txt
sol.txt
bin/*
lib/*
CMakeFiles/*
build/*
.project
.cproject

80
navigations/sbpl/CMakeLists.txt Executable file
View File

@@ -0,0 +1,80 @@
cmake_minimum_required(VERSION 2.8)
PROJECT( sbpl )
# version (e.g. for packaging)
set(SBPL_MAJOR_VERSION 1)
set(SBPL_MINOR_VERSION 3)
set(SBPL_PATCH_VERSION 1)
set(SBPL_VERSION ${SBPL_MAJOR_VERSION}.${SBPL_MINOR_VERSION}.${SBPL_PATCH_VERSION})
set(CMAKE_BUILD_TYPE Release)
include_directories(src/include)
add_library(sbpl SHARED
src/discrete_space_information/environment_nav2D.cpp
src/discrete_space_information/environment_navxythetalat.cpp
src/discrete_space_information/environment_navxythetamlevlat.cpp
src/discrete_space_information/environment_nav2Duu.cpp
src/discrete_space_information/environment_XXX.cpp
src/discrete_space_information/environment_robarm.cpp
src/heuristics/embedded_heuristic.cpp
src/planners/adplanner.cpp
src/planners/ANAplanner.cpp
src/planners/araplanner.cpp
src/planners/lazyARA.cpp
src/planners/mhaplanner.cpp
src/planners/ppcpplanner.cpp
src/planners/rstarplanner.cpp
src/planners/viplanner.cpp
src/utils/heap.cpp
src/utils/mdp.cpp
src/utils/utils.cpp
src/utils/2Dgridsearch.cpp
src/utils/config.cpp
)
set(SBPL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/include")
set(SBPL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
# support for pkg-config
set(PKG_NAME "sbpl")
set(PKG_DESC "The Search Based Planning Library")
set(PKG_SBPL_LIBS "-lsbpl")
set(pkg_conf_file_in "${CMAKE_CURRENT_SOURCE_DIR}/sbpl.pc.in")
set(pkg_conf_file "${PROJECT_BINARY_DIR}/InstallFiles/sbpl.pc")
configure_file("${pkg_conf_file_in}" "${pkg_conf_file}" @ONLY)
install(FILES ${pkg_conf_file} DESTINATION lib/pkgconfig/ COMPONENT pkgconfig)
# support for cmake-config:
configure_file(sbpl-config.cmake.in
"${PROJECT_BINARY_DIR}/InstallFiles/sbpl-config.cmake" @ONLY)
configure_file(sbpl-config-version.cmake.in
"${PROJECT_BINARY_DIR}/InstallFiles/sbpl-config-version.cmake" @ONLY)
install(FILES
"${PROJECT_BINARY_DIR}/InstallFiles/sbpl-config.cmake"
"${PROJECT_BINARY_DIR}/InstallFiles/sbpl-config-version.cmake"
DESTINATION share/sbpl/)
# support for build tree export
option(SBPL_BUILD_TREE_EXPORT "Enable build tree exports" OFF)
if (${SBPL_BUILD_TREE_EXPORT})
export(TARGETS sbpl FILE sbpl-targets.cmake)
set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}/src/include")
configure_file(
sbpl-config-tree-export.cmake.in
"${PROJECT_BINARY_DIR}/sbpl-config.cmake"
@ONLY)
export(PACKAGE sbpl)
endif()
install(DIRECTORY src/include/sbpl DESTINATION include
FILES_MATCHING PATTERN "*.h")
install(TARGETS sbpl
LIBRARY DESTINATION lib)
add_executable(test_sbpl src/test/main.cpp)
target_link_libraries(test_sbpl sbpl)
add_executable(test_adjacency_list src/test/test_adjacency_list.cpp)
target_link_libraries(test_adjacency_list sbpl)

207
navigations/sbpl/Doxyfile Executable file
View File

@@ -0,0 +1,207 @@
PROJECT_NAME = "ROS SBPL Motion Planner Library"
PROJECT_NUMBER =
OUTPUT_DIRECTORY = .
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = YES
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = src
FILE_PATTERNS = *.h *.cpp
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HIDE_UNDOC_RELATIONS = NO
HAVE_DOT = YES
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
MAX_DOT_GRAPH_DEPTH = 0
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

173
navigations/sbpl/README.txt Executable file
View File

@@ -0,0 +1,173 @@
I. Building, Installing, and Using SBPL
SBPL is available as a standalone software library. SBPL itself has no
dependencies other than the C/C++ standard library.
These build and install instructions are primarily for Linux. For other
operating systems, CMake can generate the platform-specific build and project
files necessary for building SBPL.
Versions of ROS older than Fuerte may contain packages that depend on a ROS
package version of SBPL. The recommended method to install SBPL is to install
it as a standard system library. However, if you wish to use the old ROS
package version of SBPL, you may follow these instructions.
1. Building and Installing SBPL from source
1.1 Build SBPL
SBPL uses git as its version control system. From the directory where
you want the SBPL source to reside, clone the latest source from
https://github.com/sbpl/sbpl:
git clone https://github.com/sbpl/sbpl.git
In the source directory, build the SBPL library using standard
CMake build conventions:
mkdir build
cd build
cmake ..
make
1.2 Install SBPL
Install the built library and headers onto your local system
(usually into /usr/local):
sudo make install
2. Installing SBPL from pre-built binary package
A pre-built Debian package exists on Linux for ROS distributions
Fuerte and newer. To install the Debian, run:
sudo apt-get install ros-distro-sbpl
where distro is the name of your ROS distribution. This will install
the SBPL library and associated development headers alongside other
ROS components (in /opt/ros/distro on Ubuntu distributions). A
pkg-config file is also included to allow you to locate the SBPL
library components in your build system.
3. Build your (ROS) package with SBPL as a dependency (CMake)
In the CMakeLists.txt for your (ROS) package, the following lines are
needed to find the installed SBPL files:
find_package(PkgConfig REQUIRED)
pkg_check_modules(SBPL REQUIRED sbpl)
include_directories(${SBPL_INCLUDE_DIRS})
link_directories(${SBPL_LIBRARY_DIRS})
Then, after you've declared your binaries, you need to link them
against SBPL with the following line:
target_link_libraries(your-binary-here ${SBPL_LIBRARIES})
4. Installing and Using SBPL as a ROS package
The ROS package version of SBPL was deprecated with the release of ROS
Fuerte. However, packages in ROS Electric may still require the ROS
package version of SBPL.
4.1 Install SBPL
4.1.1 Source install
SBPL uses git as its version control system. From the
directory where you want the SBPL source to reside, clone the
latest source from https://github.com/sbpl/sbpl:
git clone https://github.com/sbpl/sbpl.git
In the source directory, checkout the electric branch of the
repository to revert to the old ROS package version:
git checkout -b electric
Ensure that SBPL is on your ROS_PACKAGE_PATH and type:
rosmake sbpl
4.1.2 Binary install
SBPL is also available as a pre-built Debian in ROS Electric.
To instal the Debian, run:
sudo apt-get install ros-electric-arm-navigation
4.2 Build your ROS package with SBPL as a depency (rosbuild)
In the manifest.xml for your package, you need to add the
following line to declare the SBPL package as a dependency:
<depend package="sbpl"/>
II. Usage
Examples for how to use SBPL are in src/test/main.cpp. Please follow the
examples carefully. The library contains a number of planning problem
examples, stored as ascii files. These files (with extension .cfg) should
be passed in as arguments into the main function in main.cpp. The files
can be found in env_examples directory.
Command-line usage for the test_sbpl program can be viewed by passing '-h'
as argument to the executable.
Examples:
The following can be run from the directory containing test_sbpl,
which we assume is a build directory in the root of this project.
$ ./test_sbpl ../env_examples/nav3d/env1.cfg
Environment: xytheta; Planner: arastar; Search direction: backward
Initializing ARAPlanner...
start planning...
done planning
size of solution=16
solution size=0
Solution is found
$ ./test_sbpl --env=2d ../env_examples/nav2d/env1.cfg #2d is needed here in order to use 2d config
Environment: 2d; Planner: arastar; Search direction: backward
Initializing ARAPlanner...
start planning...
done planning
size of solution=22
Solution is found
$ ./test_sbpl --env=robarm --search-dir=forward --planner=rstar ../env_examples/robarm/env1_6d.cfg
Environment: robarm; Planner: rstar; Search direction: forward
Initializing RSTARPlanner...
start planning...
done planning
size of solution=44
Solution is found
Motion primitives files can be found in sbpl/matlab/mprim directory.
Finally, few visualization scripts can be found in
sbpl/matlab/visualization. In particular, plot_3Dpath.m function can be
used to visualize the path found by xytheta lattice planner. This
functions takes in .cfg file that specified environment and sol.txt file
that was generated within main.cpp by xythetalattice planners.
Note: If you compile the library with the ROS symbol defined, all text
output will be redirected to ROS logging constructions. Without the ROS
symbol defined, SBPL will print messages to stdout and test_sbpl will
generate a solution file, sol.txt, as well as a debugging information
file, debug.txt
III. Links
These instructions and more tutorials can be found at www.sbpl.net
For more information and documentation on SBPL visit:
http://www.ros.org/wiki/sbpl
For more information and documentation on using the x,y,theta environment
available in ROS visit:
http://www.ros.org/wiki/sbpl_lattice_planner

View File

@@ -0,0 +1,20 @@
discretization(cells): 15 15
obsthresh: 1
start(cells): 0 0
end(cells): 14 14
environment:
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
1 1 1 1 0 0 0 0 0 0 0 1 0 0 0
1 1 1 1 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
discretization(cells): 15 15
obsthresh: 1
start(cells): 0 0
end(cells): 14 14
environment:
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 1 0 0 0 0
0 0 0 0 0 0 1 1 0 0 1 0 0 0 0
0 0 0 0 0 0 1 1 1 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0.1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
1 1 1 1 0 0 0 0 0 0 0 1 0 0 0
1 1 1 1 0 0 0 0 0 0 0 0.9 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0.5 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0

View File

@@ -0,0 +1,483 @@
discretization(cells): 436 473
obsthresh: 254
cost_inscribed_thresh: 253
cost_possibly_circumscribed_thresh: 128
cellsize(meters): 0.025
nominalvel(mpersecs): 1.0
timetoturn45degsinplace(secs): 20.0
start(meters,rads): 4.0 8.0 0
end(meters,rads): 6.00 2.0 0
environment:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 12 15 17 18 17 15 12 9 5 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 9 16 24 32 40 46 49 51 49 46 40 32 24 16 9 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 30 44 59 72 84 93 99 101 99 93 84 72 59 44 30 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 13 28 46 66 87 108 128 144 157 165 168 165 157 144 128 108 87 66 46 28 13 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 17 35 59 86 115 144 173 199 221 238 248 252 248 238 221 199 173 144 115 86 59 35 17 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 67 101 137 176 215 252 253 253 253 253 253 253 253 253 253 252 215 176 137 101 67 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 19 40 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 17 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 46 28 13 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 115 86 59 35 17 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 17 35 59 86 115 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 13 28 46 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 12 40 84 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 15 46 93 157 238 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 49 99 165 248 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 49 99 165 248 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 15 46 93 157 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 12 40 84 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 17 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 17 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 19 40 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 17 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 84 40 12 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 238 157 93 46 15 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 248 165 99 49 17 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 165 99 49 17 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 238 157 93 46 15 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 84 40 12 1 1 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 9 12 15 17 18 17 15 12 9 5 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 24 32 40 46 49 51 49 46 40 32 24 16 9 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 44 59 72 84 93 99 101 99 93 84 72 59 44 30 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 66 87 108 128 144 157 165 168 165 157 144 128 108 87 66 46 28 13 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 86 115 144 173 199 221 238 248 252 248 238 221 199 173 144 115 86 59 35 17 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 152 101 101 137 176 215 252 253 253 253 253 253 253 253 253 253 252 215 176 137 101 67 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 67 101 137 176 215 252 253 253 253 253 253 253 253 253 253 252 215 176 137 101 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 17 35 59 86 115 144 173 199 221 238 248 252 248 238 221 199 173 144 115 86 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 13 28 46 66 87 108 128 144 157 165 168 165 157 144 128 108 87 66 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 30 44 59 72 84 93 99 101 99 93 84 72 59 44 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 9 16 24 32 40 46 49 51 49 46 40 32 24 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 12 15 17 18 17 15 12 9 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 2 2 2 1 1 12 40 84 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 115 86 59 35 18 8 2 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 15 46 93 157 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 46 28 13 4 1 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 49 99 165 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 40 19 8 2 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 17 5 1 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 49 99 165 248 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 15 46 93 157 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 17 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 12 40 84 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 19 40 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 0 0 1 4 13 28 46 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 0 0 0 2 8 18 35 59 86 115 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 0 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 0 0 0 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 1 0 1 4 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 5 2 8 18 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 19 13 28 46 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 17 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 40 35 59 86 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 71 67 101 137 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 115 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 176 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 40 19 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 17 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 115 86 59 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 176 137 101 67 46 28 13 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 40 71 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 35 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 19 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 84 40 12 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 238 157 93 46 15 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 248 165 99 49 17 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 165 99 49 17 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 238 157 93 46 15 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 84 40 12 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 67 35 13 9 5 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 17 40 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 49 46 40 32 24 16 9 3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 19 40 67 101 137 176 215 252 253 253 253 253 253 253 253 253 253 252 215 176 137 101 99 101 99 93 84 72 59 44 30 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 17 35 59 86 115 144 173 199 221 238 248 252 248 238 221 199 173 144 128 144 157 165 168 165 157 144 128 108 87 66 46 28 13 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 13 28 46 66 87 108 128 144 157 165 168 165 157 144 128 144 173 199 221 238 248 252 248 238 221 199 173 144 115 86 59 35 17 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 30 44 59 72 84 93 99 101 99 101 137 176 215 252 253 253 253 253 253 253 253 253 253 252 215 176 137 101 67 40 19 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 9 16 24 32 40 46 49 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 40 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 13 35 67 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 12 40 84 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 15 46 93 157 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 49 99 165 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 49 99 165 248 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 15 46 93 157 238 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 12 40 84 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 16 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 84 40 12 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 16 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 238 157 93 46 15 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 248 165 99 49 17 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 87 46 18 16 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 176 115 66 40 46 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 84 93 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 128 144 157 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 199 221 238 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 16 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 16 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 238 221 199 173 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 144 128 108 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 72 59 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 24 16 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 49 99 165 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 165 99 49 17 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 15 46 93 157 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 238 157 93 46 15 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 12 40 84 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 84 40 12 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 17 40 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 40 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 19 40 67 101 137 176 215 252 253 253 253 253 253 253 253 253 253 252 215 176 137 101 67 40 19 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 17 35 59 86 115 144 173 199 221 238 248 252 248 238 221 199 173 144 115 86 59 35 17 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 13 28 46 66 87 108 128 144 157 165 168 165 157 144 128 108 87 66 46 28 13 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 30 44 59 72 84 93 99 101 99 93 84 72 59 44 30 18 8 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 13 28 46 66 87 108 128 144 157 165 168 165 157 144 128 108 87 66 46 28 13 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 17 35 59 86 115 144 173 199 221 238 248 252 248 238 221 199 173 144 115 86 59 35 17 5 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 19 40 67 101 137 176 215 252 253 253 253 253 253 253 253 253 253 252 215 176 137 101 67 40 19 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 17 40 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 40 17 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 67 35 13 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 152 101 59 28 8 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 12 40 84 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 84 40 12 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 15 46 93 157 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 238 157 93 46 15 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 49 99 165 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 165 99 49 17 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 24 16 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 72 59 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 144 128 108 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 238 221 199 173 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 16 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 16 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 5 2 2 1 2 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 17 49 99 165 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 17 15 12 9 18 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 15 46 93 157 238 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 49 46 40 32 24 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 12 40 84 144 221 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 93 84 72 59 51 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 32 72 128 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 144 128 108 99 101 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 24 59 108 173 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 199 173 165 157 168 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 16 44 87 144 215 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 248 238 221 252 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 9 30 66 115 176 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 18 46 86 137 199 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 8 28 59 101 152 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 13 35 67 108 157 212 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 17 40 71 108 152 199 248 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 19 40 67 101 137 176 215 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 5 17 35 59 86 115 144 173 199 221 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 13 28 46 66 87 108 128 144 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 8 18 30 44 59 72 87 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 9 16 24 32 44 59 72 84 93 99 108 128 144 157 165 173 199 221 238 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 16 24 32 40 46 49 59 72 84 93 99 108 128 144 157 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 16 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 253 253 253 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 254 254 253 253 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 254 254 254 253 253 253 253 253 253 253 253 253 253 253 253 252 168 101 51 18 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 165 99 49 17 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 238 157 93 46 15 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 16 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 221 144 84 40 12 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 128 72 32 9 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 252 173 108 59 24 5 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 215 144 87 44 16 2 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 176 115 66 30 9 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 16 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 199 137 86 46 18 3 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 152 101 59 28 8 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 173 199 221 238 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 212 157 108 67 35 13 2 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 108 128 144 157 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 253 248 199 152 108 71 40 17 4 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 108 128 144 157 165 173 199 221 238 248 252 253 253 253 253 253 253 253 253 253 253 253 252 215 176 137 101 67 40 19 5 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 59 72 84 93 99 108 128 144 157 165 173 199 221 238 248 252 252 252 248 238 221 199 173 144 115 86 59 35 17 5 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 16 24 32 40 46 49 59 72 84 93 99 108 128 144 157 165 168 168 168 165 157 144 128 108 87 66 46 28 13 4 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 5 9 12 15 17 24 32 40 46 49 59 72 84 93 99 101 101 101 99 93 84 72 59 44 30 18 8 2 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 24 32 40 46 49 51 51 51 49 46 40 32 24 16 9 3 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 5 9 12 15 17 18 18 18 17 15 12 9 5 2 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 2 2 2 2 2 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

View File

@@ -0,0 +1,25 @@
discretization(cells): 15 15
obsthresh: 1
cost_inscribed_thresh: 1
cost_possibly_circumscribed_thresh: 0
cellsize(meters): 0.025
nominalvel(mpersecs): 1.0
timetoturn45degsinplace(secs): 2.0
start(meters,rads): 0.11 0.11 0
end(meters,rads): 0.35 0.3 0
environment:
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
1 1 1 1 0 0 0 0 0 0 0 1 0 0 0
1 1 1 1 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
environmentsize(meters): 50.0 50.0
discretization(cells): 50 50
basex(cells): 25
linklengths(meters): 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0
linkstartangles(degrees): 90.0 90.0 90.0 90.0 0.0 0.0 270.0 270.0 0.0 0.0 90.0 90.0 90.0 90.0 90.0 90.0 90.0 90.0 90.0 90.0
endeffectorgoal(cells): 10 10
environment:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

View File

@@ -0,0 +1,57 @@
environmentsize(meters): 50.0 50.0
discretization(cells): 50 50
basex(cells): 25
linklengths(meters): 20.0 10.0 10.0 5.0 10.0 5.0
linkstartangles(degrees): 90.0 0.0 90.0 90.0 0.0 90.0
endeffectorgoal(cells): 10 10
environment:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

View File

@@ -0,0 +1,57 @@
environmentsize(meters): 50.0 50.0
discretization(cells): 50 50
basex(cells): 25
linklengths(meters): 20.0 10.0 10.0 5.0 10.0 10.0
linkstartangles(degrees): 90.0 0.0 90.0 90.0 0.0 90.0
endeffectorgoal(cells): 10 3
environment:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

View File

@@ -0,0 +1,57 @@
environmentsize(meters): 50.0 50.0
discretization(cells): 50 50
basex(cells): 25
linklengths(meters): 20.0 10.0 10.0 5.0 10.0 10.0
linkstartangles(degrees): 90.0 0.0 90.0 90.0 0.0 90.0
endeffectorgoal(cells): 10 3
environment:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

View File

@@ -0,0 +1,57 @@
environmentsize(meters): 50.0 50.0
discretization(cells): 50 50
basex(cells): 25
linklengths(meters): 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0
linkstartangles(degrees): 90.0 90.0 90.0 90.0 0.0 0.0 270.0 270.0 0.0 0.0 90.0 90.0 90.0 90.0 90.0 90.0 90.0 90.0 90.0 90.0
endeffectorgoal(cells): 10 10
environment:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,316 @@
% /*
% * Copyright (c) 2008, Maxim Likhachev
% * All rights reserved.
% *
% * Redistribution and use in source and binary forms, with or without
% * modification, are permitted provided that the following conditions are met:
% *
% * * Redistributions of source code must retain the above copyright
% * notice, this list of conditions and the following disclaimer.
% * * Redistributions in binary form must reproduce the above copyright
% * notice, this list of conditions and the following disclaimer in the
% * documentation and/or other materials provided with the distribution.
% * * Neither the name of the Carnegie Mellon University nor the names of its
% * contributors may be used to endorse or promote products derived from
% * this software without specific prior written permission.
% *
% * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% * POSSIBILITY OF SUCH DAMAGE.
% */
function[] = genmprim(outfilename)
%
%generates motion primitives and saves them into file
%
%written by Maxim Likhachev
%---------------------------------------------------
%
%defines
LINESEGMENT_MPRIMS = 1; %set the desired type of motion primitives
UNICYCLE_MPRIMS = 0;
if LINESEGMENT_MPRIMS == 1
resolution = 0.01;
numberofangles = 32; %preferably a power of 2, definitely multiple of 8
numberofprimsperangle = 16;
%multipliers (multiplier is used as costmult*cost)
forwardcostmult = 1;
backwardcostmult = 5;
forwardandturncostmult = 1;
sidestepcostmult = 50;
turninplacecostmult = 50;
%note, what is shown x,y,theta changes (not absolute numbers)
%0 degreees
basemprimendpts0_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult
%x aligned with the heading of the robot, angles are positive
%counterclockwise
%0 theta change
basemprimendpts0_c(1,:) = [1 0 0 forwardcostmult];
basemprimendpts0_c(2,:) = [4 0 0 forwardcostmult];
basemprimendpts0_c(3,:) = [8 0 0 forwardcostmult];
basemprimendpts0_c(4,:) = [6 2 0 sidestepcostmult];
basemprimendpts0_c(5,:) = [6 -2 0 sidestepcostmult];
basemprimendpts0_c(6,:) = [2 3 0 sidestepcostmult];
basemprimendpts0_c(7,:) = [2 -3 0 sidestepcostmult];
basemprimendpts0_c(8,:) = [-5 0 0 backwardcostmult];
%1/32 theta change
basemprimendpts0_c(9,:) = [6 2 1 forwardandturncostmult];
basemprimendpts0_c(10,:) = [6 -2 -1 forwardandturncostmult];
%2/32 theta change
basemprimendpts0_c(11,:) = [4 3 2 forwardandturncostmult];
basemprimendpts0_c(12,:) = [4 -3 -2 forwardandturncostmult];
%turn in place
basemprimendpts0_c(13,:) = [0 0 1 turninplacecostmult];
basemprimendpts0_c(14,:) = [0 0 -1 turninplacecostmult];
basemprimendpts0_c(15,:) = [0 0 3 turninplacecostmult];
basemprimendpts0_c(16,:) = [0 0 -3 turninplacecostmult];
%45 degrees
basemprimendpts45_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%x aligned with the heading of the robot, angles are positive
%counterclockwise
%0 theta change
basemprimendpts45_c(1,:) = [1 1 0 forwardcostmult];
basemprimendpts45_c(2,:) = [3 3 0 forwardcostmult];
basemprimendpts45_c(3,:) = [6 6 0 forwardcostmult];
basemprimendpts45_c(4,:) = [2 6 0 sidestepcostmult];
basemprimendpts45_c(5,:) = [6 2 0 sidestepcostmult];
basemprimendpts45_c(6,:) = [0 4 0 sidestepcostmult];
basemprimendpts45_c(7,:) = [4 0 0 sidestepcostmult];
basemprimendpts45_c(8,:) = [-4 -4 0 backwardcostmult];
%1/32 theta change
basemprimendpts45_c(9,:) = [2 6 1 forwardandturncostmult];
basemprimendpts45_c(10,:) = [6 2 -1 forwardandturncostmult];
%2/32 theta change
basemprimendpts45_c(11,:) = [1 5 2 forwardandturncostmult];
basemprimendpts45_c(12,:) = [5 1 -2 forwardandturncostmult];
%turn in place
basemprimendpts45_c(13,:) = [0 0 1 turninplacecostmult];
basemprimendpts45_c(14,:) = [0 0 -1 turninplacecostmult];
basemprimendpts45_c(15,:) = [0 0 3 turninplacecostmult];
basemprimendpts45_c(16,:) = [0 0 -3 turninplacecostmult];
%22.5 degrees
basemprimendpts22p5_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%x aligned with the heading of the robot, angles are positive
%counterclockwise
%0 theta change
basemprimendpts22p5_c(1,:) = [2 1 0 forwardcostmult];
basemprimendpts22p5_c(2,:) = [4 2 0 forwardcostmult];
basemprimendpts22p5_c(3,:) = [6 3 0 forwardcostmult];
basemprimendpts22p5_c(4,:) = [4 4 0 sidestepcostmult];
basemprimendpts22p5_c(5,:) = [6 2 0 sidestepcostmult];
basemprimendpts22p5_c(6,:) = [0 3 0 sidestepcostmult];
basemprimendpts22p5_c(7,:) = [4 -1 0 sidestepcostmult];
basemprimendpts22p5_c(8,:) = [-4 -2 0 backwardcostmult];
%1/32 theta change
basemprimendpts22p5_c(9,:) = [4 4 1 forwardandturncostmult];
basemprimendpts22p5_c(10,:) = [6 2 -1 forwardandturncostmult];
%2/32 theta change
basemprimendpts22p5_c(11,:) = [2 4 2 forwardandturncostmult];
basemprimendpts22p5_c(12,:) = [6 0 -2 forwardandturncostmult];
%turn in place
basemprimendpts22p5_c(13,:) = [0 0 1 turninplacecostmult];
basemprimendpts22p5_c(14,:) = [0 0 -1 turninplacecostmult];
basemprimendpts22p5_c(15,:) = [0 0 3 turninplacecostmult];
basemprimendpts22p5_c(16,:) = [0 0 -3 turninplacecostmult];
%11.25 degrees
basemprimendpts11p25_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%x aligned with the heading of the robot, angles are positive
%counterclockwise
%0 theta change
basemprimendpts11p25_c(1,:) = [3 1 0 forwardcostmult];
basemprimendpts11p25_c(2,:) = [6 2 0 forwardcostmult];
basemprimendpts11p25_c(3,:) = [9 3 0 forwardcostmult];
basemprimendpts11p25_c(4,:) = [4 3 0 sidestepcostmult];
basemprimendpts11p25_c(5,:) = [6 0 0 sidestepcostmult];
basemprimendpts11p25_c(6,:) = [1 3 0 sidestepcostmult];
basemprimendpts11p25_c(7,:) = [3 -2 0 sidestepcostmult];
basemprimendpts11p25_c(8,:) = [-6 -2 0 backwardcostmult];
%1/32 theta change
basemprimendpts11p25_c(9,:) = [4 3 1 forwardandturncostmult];
basemprimendpts11p25_c(10,:) = [6 0 -1 forwardandturncostmult];
%2/32 theta change
basemprimendpts11p25_c(11,:) = [2 4 2 forwardandturncostmult];
basemprimendpts11p25_c(12,:) = [5 -1 -2 forwardandturncostmult];
%turn in place
basemprimendpts11p25_c(13,:) = [0 0 1 turninplacecostmult];
basemprimendpts11p25_c(14,:) = [0 0 -1 turninplacecostmult];
basemprimendpts11p25_c(15,:) = [0 0 3 turninplacecostmult];
basemprimendpts11p25_c(16,:) = [0 0 -3 turninplacecostmult];
%33.75 degrees
basemprimendpts33p75_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult
%x aligned with the heading of the robot, angles are positive
%counterclockwise
%0 theta change
basemprimendpts33p75_c(1,:) = [3 2 0 forwardcostmult];
basemprimendpts33p75_c(2,:) = [6 4 0 forwardcostmult];
basemprimendpts33p75_c(3,:) = [9 6 0 forwardcostmult];
basemprimendpts33p75_c(4,:) = [4 5 0 sidestepcostmult];
basemprimendpts33p75_c(5,:) = [6 2 0 sidestepcostmult];
basemprimendpts33p75_c(6,:) = [0 4 0 sidestepcostmult];
basemprimendpts33p75_c(7,:) = [3 -2 0 sidestepcostmult];
basemprimendpts33p75_c(8,:) = [-6 -4 0 backwardcostmult];
%1/32 theta change
basemprimendpts33p75_c(9,:) = [4 5 1 forwardandturncostmult];
basemprimendpts33p75_c(10,:) = [6 2 -1 forwardandturncostmult];
%2/32 theta change
basemprimendpts33p75_c(11,:) = [1 5 2 forwardandturncostmult];
basemprimendpts33p75_c(12,:) = [3 -2 -2 forwardandturncostmult];
%turn in place
basemprimendpts33p75_c(13,:) = [0 0 1 turninplacecostmult];
basemprimendpts33p75_c(14,:) = [0 0 -1 turninplacecostmult];
basemprimendpts33p75_c(15,:) = [0 0 3 turninplacecostmult];
basemprimendpts33p75_c(16,:) = [0 0 -3 turninplacecostmult];
elseif UNICYCLE_MPRIMS == 1
fprintf(1, 'ERROR: unsupported mprims type\n');
return;
else
fprintf(1, 'ERROR: undefined mprims type\n');
return;
end;
fout = fopen(outfilename, 'w');
%write the header
fprintf(fout, 'resolution_m: %f\n', resolution);
fprintf(fout, 'numberofangles: %d\n', numberofangles);
fprintf(fout, 'totalnumberofprimitives: %d\n', numberofprimsperangle*numberofangles);
%iterate over angles
for angleind = 1:numberofangles
figure(1);
hold off;
text(0, 0, int2str(angleind));
%iterate over primitives
for primind = 1:numberofprimsperangle
fprintf(fout, 'primID: %d\n', primind-1);
fprintf(fout, 'startangle_c: %d\n', angleind-1);
%current angle
currentangle = (angleind-1)*2*pi/numberofangles;
currentangle_36000int = round((angleind-1)*36000/numberofangles);
%compute which template to use
if (rem(currentangle_36000int, 9000) == 0)
basemprimendpts_c = basemprimendpts0_c(primind,:);
angle = currentangle;
elseif (rem(currentangle_36000int, 4500) == 0)
basemprimendpts_c = basemprimendpts45_c(primind,:);
angle = currentangle - 45*pi/180;
elseif (rem(currentangle_36000int-7875, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
basemprimendpts_c(1) = basemprimendpts33p75_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts33p75_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts33p75_c(primind, 3); %reverse the angle as well
angle = currentangle - 78.75*pi/180;
fprintf(1, '78p75\n');
elseif (rem(currentangle_36000int-6750, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
basemprimendpts_c(1) = basemprimendpts22p5_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts22p5_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts22p5_c(primind, 3); %reverse the angle as well
%fprintf(1, '%d %d %d onto %d %d %d\n', basemprimendpts22p5_c(1), basemprimendpts22p5_c(2), basemprimendpts22p5_c(3), ...
% basemprimendpts_c(1), basemprimendpts_c(2), basemprimendpts_c(3));
angle = currentangle - 67.5*pi/180;
fprintf(1, '67p5\n');
elseif (rem(currentangle_36000int-5625, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
basemprimendpts_c(1) = basemprimendpts11p25_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts11p25_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts11p25_c(primind, 3); %reverse the angle as well
angle = currentangle - 56.25*pi/180;
fprintf(1, '56p25\n');
elseif (rem(currentangle_36000int-3375, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
angle = currentangle - 33.75*pi/180;
fprintf(1, '33p75\n');
elseif (rem(currentangle_36000int-2250, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
angle = currentangle - 22.5*pi/180;
fprintf(1, '22p5\n');
elseif (rem(currentangle_36000int-1125, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
angle = currentangle - 11.25*pi/180;
fprintf(1, '11p25\n');
else
fprintf(1, 'ERROR: invalid angular resolution. angle = %d\n', currentangle_36000int);
return;
end;
%now figure out what action will be
baseendpose_c = basemprimendpts_c(1:3);
additionalactioncostmult = basemprimendpts_c(4);
endx_c = round(baseendpose_c(1)*cos(angle) - baseendpose_c(2)*sin(angle));
endy_c = round(baseendpose_c(1)*sin(angle) + baseendpose_c(2)*cos(angle));
endtheta_c = rem(angleind - 1 + baseendpose_c(3), numberofangles);
endpose_c = [endx_c endy_c endtheta_c];
fprintf(1, 'rotation angle=%f\n', angle*180/pi);
if baseendpose_c(2) == 0 & baseendpose_c(3) == 0
%fprintf(1, 'endpose=%d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
end;
%generate intermediate poses (remember they are w.r.t 0,0 (and not
%centers of the cells)
numofsamples = 10;
intermcells_m = zeros(numofsamples,3);
if LINESEGMENT_MPRIMS == 1
startpt = [0 0 currentangle];
endpt = [endpose_c(1)*resolution endpose_c(2)*resolution ...
rem(angleind - 1 + baseendpose_c(3), numberofangles)*2*pi/numberofangles];
intermcells_m = zeros(numofsamples,3);
for iind = 1:numofsamples
intermcells_m(iind,:) = [startpt(1) + (endpt(1) - startpt(1))*(iind-1)/(numofsamples-1) ...
startpt(2) + (endpt(2) - startpt(2))*(iind-1)/(numofsamples-1) ...
0];
rotation_angle = (baseendpose_c(3) ) * (2*pi/numberofangles);
intermcells_m(iind,3) = rem(startpt(3) + (rotation_angle)*(iind-1)/(numofsamples-1), 2*pi);
end;
end;
%write out
fprintf(fout, 'endpose_c: %d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
fprintf(fout, 'additionalactioncostmult: %d\n', additionalactioncostmult);
fprintf(fout, 'intermediateposes: %d\n', size(intermcells_m,1));
for interind = 1:size(intermcells_m, 1)
fprintf(fout, '%.4f %.4f %.4f\n', intermcells_m(interind,1), intermcells_m(interind,2), intermcells_m(interind,3));
end;
plot(intermcells_m(:,1), intermcells_m(:,2));
text(intermcells_m(numofsamples,1), intermcells_m(numofsamples,2), int2str(endpose_c(3)));
hold on;
end;
grid;
pause;
end;
fclose('all');

View File

@@ -0,0 +1,279 @@
% /*
% * Copyright (c) 2008, Maxim Likhachev
% * All rights reserved.
% *
% * Redistribution and use in source and binary forms, with or without
% * modification, are permitted provided that the following conditions are met:
% *
% * * Redistributions of source code must retain the above copyright
% * notice, this list of conditions and the following disclaimer.
% * * Redistributions in binary form must reproduce the above copyright
% * notice, this list of conditions and the following disclaimer in the
% * documentation and/or other materials provided with the distribution.
% * * Neither the name of the Carnegie Mellon University nor the names of its
% * contributors may be used to endorse or promote products derived from
% * this software without specific prior written permission.
% *
% * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% * POSSIBILITY OF SUCH DAMAGE.
% */
function[] = genmprim_unicycle(outfilename)
%
%generates motion primitives and saves them into file
%
%written by Maxim Likhachev
%---------------------------------------------------
%
%defines
UNICYCLE_MPRIM_16DEGS = 1;
if UNICYCLE_MPRIM_16DEGS == 1
resolution = 0.025;
numberofangles = 16; %preferably a power of 2, definitely multiple of 8
numberofprimsperangle = 5;
%multipliers (multiplier is used as costmult*cost)
forwardcostmult = 1;
backwardcostmult = 5;
forwardandturncostmult = 2;
sidestepcostmult = 10;
turninplacecostmult = 5;
%note, what is shown x,y,theta changes (not absolute numbers)
%0 degreees
basemprimendpts0_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult
%x aligned with the heading of the robot, angles are positive
%counterclockwise
%0 theta change
basemprimendpts0_c(1,:) = [1 0 0 forwardcostmult];
basemprimendpts0_c(2,:) = [8 0 0 forwardcostmult];
basemprimendpts0_c(3,:) = [-1 0 0 backwardcostmult];
%1/16 theta change
basemprimendpts0_c(4,:) = [8 1 1 forwardandturncostmult];
basemprimendpts0_c(5,:) = [8 -1 -1 forwardandturncostmult];
%turn in place
%basemprimendpts0_c(6,:) = [0 0 1 turninplacecostmult];
%basemprimendpts0_c(7,:) = [0 0 -1 turninplacecostmult];
%45 degrees
basemprimendpts45_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%x aligned with the heading of the robot, angles are positive
%counterclockwise
%0 theta change
basemprimendpts45_c(1,:) = [1 1 0 forwardcostmult];
basemprimendpts45_c(2,:) = [6 6 0 forwardcostmult];
basemprimendpts45_c(3,:) = [-1 -1 0 backwardcostmult];
%1/16 theta change
basemprimendpts45_c(4,:) = [5 7 1 forwardandturncostmult];
basemprimendpts45_c(5,:) = [7 5 -1 forwardandturncostmult];
%turn in place
%basemprimendpts45_c(6,:) = [0 0 1 turninplacecostmult];
%basemprimendpts45_c(7,:) = [0 0 -1 turninplacecostmult];
%22.5 degrees
basemprimendpts22p5_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%x aligned with the heading of the robot, angles are positive
%counterclockwise
%0 theta change
basemprimendpts22p5_c(1,:) = [2 1 0 forwardcostmult];
basemprimendpts22p5_c(2,:) = [6 3 0 forwardcostmult];
basemprimendpts22p5_c(3,:) = [-2 -1 0 backwardcostmult];
%1/16 theta change
basemprimendpts22p5_c(4,:) = [5 4 1 forwardandturncostmult];
basemprimendpts22p5_c(5,:) = [7 2 -1 forwardandturncostmult];
%turn in place
%basemprimendpts22p5_c(6,:) = [0 0 1 turninplacecostmult];
%basemprimendpts22p5_c(7,:) = [0 0 -1 turninplacecostmult];
else
fprintf(1, 'ERROR: undefined mprims type\n');
return;
end;
fout = fopen(outfilename, 'w');
%write the header
fprintf(fout, 'resolution_m: %f\n', resolution);
fprintf(fout, 'numberofangles: %d\n', numberofangles);
fprintf(fout, 'totalnumberofprimitives: %d\n', numberofprimsperangle*numberofangles);
%iterate over angles
for angleind = 1:numberofangles
figure(1);
hold off;
text(0, 0, int2str(angleind));
%iterate over primitives
for primind = 1:numberofprimsperangle
fprintf(fout, 'primID: %d\n', primind-1);
fprintf(fout, 'startangle_c: %d\n', angleind-1);
%current angle
currentangle = (angleind-1)*2*pi/numberofangles;
currentangle_36000int = round((angleind-1)*36000/numberofangles);
%compute which template to use
if (rem(currentangle_36000int, 9000) == 0)
basemprimendpts_c = basemprimendpts0_c(primind,:);
angle = currentangle;
elseif (rem(currentangle_36000int, 4500) == 0)
basemprimendpts_c = basemprimendpts45_c(primind,:);
angle = currentangle - 45*pi/180;
elseif (rem(currentangle_36000int-7875, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
basemprimendpts_c(1) = basemprimendpts33p75_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts33p75_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts33p75_c(primind, 3); %reverse the angle as well
angle = currentangle - 78.75*pi/180;
fprintf(1, '78p75\n');
elseif (rem(currentangle_36000int-6750, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
basemprimendpts_c(1) = basemprimendpts22p5_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts22p5_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts22p5_c(primind, 3); %reverse the angle as well
%fprintf(1, '%d %d %d onto %d %d %d\n', basemprimendpts22p5_c(1), basemprimendpts22p5_c(2), basemprimendpts22p5_c(3), ...
% basemprimendpts_c(1), basemprimendpts_c(2), basemprimendpts_c(3));
angle = currentangle - 67.5*pi/180;
fprintf(1, '67p5\n');
elseif (rem(currentangle_36000int-5625, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
basemprimendpts_c(1) = basemprimendpts11p25_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts11p25_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts11p25_c(primind, 3); %reverse the angle as well
angle = currentangle - 56.25*pi/180;
fprintf(1, '56p25\n');
elseif (rem(currentangle_36000int-3375, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
angle = currentangle - 33.75*pi/180;
fprintf(1, '33p75\n');
elseif (rem(currentangle_36000int-2250, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
angle = currentangle - 22.5*pi/180;
fprintf(1, '22p5\n');
elseif (rem(currentangle_36000int-1125, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
angle = currentangle - 11.25*pi/180;
fprintf(1, '11p25\n');
else
fprintf(1, 'ERROR: invalid angular resolution. angle = %d\n', currentangle_36000int);
return;
end;
%now figure out what action will be
baseendpose_c = basemprimendpts_c(1:3);
additionalactioncostmult = basemprimendpts_c(4);
endx_c = round(baseendpose_c(1)*cos(angle) - baseendpose_c(2)*sin(angle));
endy_c = round(baseendpose_c(1)*sin(angle) + baseendpose_c(2)*cos(angle));
endtheta_c = rem(angleind - 1 + baseendpose_c(3), numberofangles);
endpose_c = [endx_c endy_c endtheta_c];
fprintf(1, 'rotation angle=%f\n', angle*180/pi);
if baseendpose_c(2) == 0 & baseendpose_c(3) == 0
%fprintf(1, 'endpose=%d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
end;
%generate intermediate poses (remember they are w.r.t 0,0 (and not
%centers of the cells)
numofsamples = 10;
intermcells_m = zeros(numofsamples,3);
if UNICYCLE_MPRIM_16DEGS == 1
startpt = [0 0 currentangle];
endpt = [endpose_c(1)*resolution endpose_c(2)*resolution ...
rem(angleind - 1 + baseendpose_c(3), numberofangles)*2*pi/numberofangles];
intermcells_m = zeros(numofsamples,3);
if ((endx_c == 0 & endy_c == 0) | baseendpose_c(3) == 0) %turn in place or move forward
for iind = 1:numofsamples
intermcells_m(iind,:) = [startpt(1) + (endpt(1) - startpt(1))*(iind-1)/(numofsamples-1) ...
startpt(2) + (endpt(2) - startpt(2))*(iind-1)/(numofsamples-1) ...
0];
rotation_angle = (baseendpose_c(3) ) * (2*pi/numberofangles);
intermcells_m(iind,3) = rem(startpt(3) + (rotation_angle)*(iind-1)/(numofsamples-1), 2*pi);
end;
else %unicycle-based move forward or backward
R = [cos(startpt(3)) sin(endpt(3)) - sin(startpt(3));
sin(startpt(3)) -(cos(endpt(3)) - cos(startpt(3)))];
S = pinv(R)*[endpt(1) - startpt(1); endpt(2) - startpt(2)];
l = S(1);
tvoverrv = S(2);
rv = (baseendpose_c(3)*2*pi/numberofangles + l/tvoverrv);
tv = tvoverrv*rv;
if l < 0
fprintf(1, 'WARNING: l = %d < 0 -> bad action start/end points\n', l);
l = 0;
end;
%compute rv
%rv = baseendpose_c(3)*2*pi/numberofangles;
%compute tv
%tvx = (endpt(1) - startpt(1))*rv/(sin(endpt(3)) - sin(startpt(3)))
%tvy = -(endpt(2) - startpt(2))*rv/(cos(endpt(3)) - cos(startpt(3)))
%tv = (tvx + tvy)/2.0;
%generate samples
for iind = 1:numofsamples
dt = (iind-1)/(numofsamples-1);
%dtheta = rv*dt + startpt(3);
%intermcells_m(iind,:) = [startpt(1) + tv/rv*(sin(dtheta) - sin(startpt(3))) ...
% startpt(2) - tv/rv*(cos(dtheta) - cos(startpt(3))) ...
% dtheta];
if(dt*tv < l)
intermcells_m(iind,:) = [startpt(1) + dt*tv*cos(startpt(3)) ...
startpt(2) + dt*tv*sin(startpt(3)) ...
startpt(3)];
else
dtheta = rv*(dt - l/tv) + startpt(3);
intermcells_m(iind,:) = [startpt(1) + l*cos(startpt(3)) + tvoverrv*(sin(dtheta) - sin(startpt(3))) ...
startpt(2) + l*sin(startpt(3)) - tvoverrv*(cos(dtheta) - cos(startpt(3))) ...
dtheta];
end;
end;
%correct
errorxy = [endpt(1) - intermcells_m(numofsamples,1) ...
endpt(2) - intermcells_m(numofsamples,2)];
fprintf(1, 'l=%f errx=%f erry=%f\n', l, errorxy(1), errorxy(2));
interpfactor = [0:1/(numofsamples-1):1];
intermcells_m(:,1) = intermcells_m(:,1) + errorxy(1)*interpfactor';
intermcells_m(:,2) = intermcells_m(:,2) + errorxy(2)*interpfactor';
end;
end;
%write out
fprintf(fout, 'endpose_c: %d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
fprintf(fout, 'additionalactioncostmult: %d\n', additionalactioncostmult);
fprintf(fout, 'intermediateposes: %d\n', size(intermcells_m,1));
for interind = 1:size(intermcells_m, 1)
fprintf(fout, '%.4f %.4f %.4f\n', intermcells_m(interind,1), intermcells_m(interind,2), intermcells_m(interind,3));
end;
plot(intermcells_m(:,1), intermcells_m(:,2));
axis([-0.3 0.3 -0.3 0.3]);
text(intermcells_m(numofsamples,1), intermcells_m(numofsamples,2), int2str(endpose_c(3)));
hold on;
end;
grid;
pause;
end;
fclose('all');

View File

@@ -0,0 +1,741 @@
function[] = genmprim_unicycle_circular_non_uniform (outfilename)
% Generates circular motion primitives with min turning radius and saves them into a file.
% For each angle from the list_of_angles array generates a set of 4 forward moving motion primitives
% and 4 symmetric backward moving motion primitives.
%
% This function takes one optional argument - 'outfilename', which specifies
% the location of the output file where motion primitives data is saved.
% If this argiment is omitted, the file name is hardcoded.
%
% The script builds the following types of motion primitives with unique ids for each
% angle from the list_of_angles array:
%
% if has_turn_in_place_prims == 0
%
% 1 - short forward
% 2 - long forward
% 3 - forward and turn left
% 4 - forward and turn right
% 5 - short backward
% 6 - long backward
% 7 - backward and turn left
% 8 - backward and turn right
%
% if has_turn_in_place_prims == 1
%
% 1 - short forward
% 2 - long forward
% 3 - forward and turn left
% 4 - forward and turn right
% 5 - turn in place forward
% 6 - short backward
% 7 - long backward
% 8 - backward and turn left
% 9 - backward and turn right
% 10 - turn in place backward
%
%
% Configurarion parameters:
% resolution grid resolution
% errmin max acceptable error for the distance between the endpoint of the motion primitive and the grid node.
% rmin_m min acceptable turning radius im meters
% xmin min x coordinate for the endpoint of the circular motion primitive
% ymin min y coordinate for the endpoint of the circular motion primitive
% xmax max x coordinate for the endpoint of the circular motion primitive
% ymax max y coordinate for the endpoint of the circular motion primitive
% countmax max number of different acceptable (by errmin and rmax) primitives of different lengths to calculate before choosing the best among them.
%
% alfa the angle satisfying the condition: alfa = atan(0.5)= 26.56505118 degrees, 0.46364761 radians
% numberofangles number of angles for which motion primitives are generated
% number_of_base_prims_per_angle number of base (forward moving) primitives per angle
% numberofbaseangles number of base angles: 0, alfa and 45
% degrees. All other angles are rotations or reflections of these base angles.
% has_backward_prims can be 1 or 0, if 0, backward moving primitives are not generated.
% list_if_angles list of angles for which sets of motion primitives are built
% degrees: 0 26.5651 45.00 63.4349 90.00 116.5651 135.00 153.4349 180.00 206.5651 225.00 243.4349 270.00 296.5651 315.00 333.4349 360.00
% radians: 0 0.4538 0.7854 1.1170 1.5708 2.0246 2.3562 2.6878 3.1416 3.5954 3.9270 4.2586 4.7124 5.1662 5.4978 5.8294 6.2832
%
% Cost multipliers (multiplier is used as costmult*cost)
% forwardcostmult cost multiplier for the forward motion
% backwardcostmult cost multiplier for the backward motion
% forwardandturncostmult cost multiplier for the forward-and-turn motion
% backwardandturncostmult cost multiplier for the backward-and-turn motion
%
% This script prints 3 coordinates for each motion primitive: x, y, theta
%%%%%
fprintf(1, 'genmprim_unicycle_circular_non_uniform\n');
% configuration parameters
resolution = 0.1; %0.025; %0.1;
errmin = 0.05; %0.05;
rmin_m = 3.0; %1.0;
rmin_c = rmin_m/resolution;
fprintf(1, 'resolution=%f rmin_m=%f meters rmin_c=%f cells errmin=%f\n', resolution, rmin_m, rmin_c, errmin);
if nargin < 1
%outputFile = 0;
basefilename = 'non_uniform_';
outfilename = generate_file_name(basefilename, resolution, rmin_m, errmin);
fprintf(1, 'outfilename = %s\n', outfilename);
end
xmin = 0;
ymin = 0;
xmax = 40;
ymax = 40;
countmax = 40;
interm_spacing_m = resolution/2; % Approximate spacing of intermediate poses in meters
interm_spacing_c = interm_spacing_m/resolution;
interm_spacing_rad = 0.05; % Approximate spacing of intermediate poses in radians
fprintf(1, 'xmin=%f xmax=%f ymin=%f ymax=%f\n', xmin, xmax, ymin, ymax);
fprintf(1, 'countmax=%d interm_spacing_m=%f meters interm_spacing_rad=%f radians\n', countmax, interm_spacing_m, interm_spacing_rad);
numberofangles = 16;
%number_of_base_prims_per_angle = 4;
%max_number_of_prims_per_angle = 8;
numberofbaseangles = 3; % 0, alfa and 45 degrees
has_backward_prims = 1;
has_turn_in_place_prims = 1;
number_of_base_prims_per_angle = 4 + has_turn_in_place_prims;
max_number_of_prims_per_angle = 2 * number_of_base_prims_per_angle; %this is only needed for arrays memory allocations
numberofprimsperangle = (1 + has_backward_prims) * number_of_base_prims_per_angle; % This is the total number of primitives per angle
totalnumberofprimitives = numberofprimsperangle*numberofangles;
fprintf(1, 'numberofangles=%d number_of_base_prims_per_angle=%d\n', numberofangles, number_of_base_prims_per_angle);
fprintf(1, 'has_backward_prims=%d\n', has_backward_prims);
fprintf(1, 'has_turn_in_place_prims=%d\n', has_turn_in_place_prims);
fprintf(1, 'numberofprimsperangle=%d totalnumberofprimitives=%d\n', numberofprimsperangle, totalnumberofprimitives);
start_x = 0.0;
start_y = 0.0;
%multipliers (multiplier is used as costmult*cost)
forwardcostmult = 1;
backwardcostmult = 5;
forwardandturncostmult = 2;
backwardandturncostmult = 3;
turninplacecostmult = 5;
costmult = []
if (has_turn_in_place_prims)
costmult = [forwardcostmult, forwardcostmult, forwardandturncostmult, forwardandturncostmult, turninplacecostmult, backwardcostmult, backwardcostmult, backwardandturncostmult, backwardandturncostmult, turninplacecostmult];
else
costmult = [forwardcostmult, forwardcostmult, forwardandturncostmult, forwardandturncostmult, tbackwardcostmult, backwardcostmult, backwardandturncostmult, backwardandturncostmult];
end;
% list of angles increments in discrete units for the end pose of the primitive relative to the start pose
prim_angle_increments = [0, 0, 1, -1];
alfa = 26.56505118;
alfa1 = alfa*100000000;
beta = 90 - alfa;
beta1 = beta*100000000;
imax = has_backward_prims + 1;
fprintf(1, 'alfa1=%f beta=%f beta1=%f imax=%d\n', alfa1, beta, beta1, imax);
%list_of_angles (degrees): 0 26.5651 45.00 63.4349 90.00 116.5651 135.00 153.4349 180.00 206.5651 225.00 243.4349 270.00 296.5651 315.00 333.4349 360.00
%list_of_angles (radians): 0 0.4538 0.7854 1.1170 1.5708 2.0246 2.3562 2.6878 3.1416 3.5954 3.9270 4.2586 4.7124 5.1662 5.4978 5.8294 6.2832
fprintf(1, '*******************************\n');
list_of_angles = zeros(1, numberofangles+1);
list_of_angles(1:2:17) = (0:45:360);
list_of_angles([2 6 10 14]) = list_of_angles([1 5 9 13]) + alfa;
list_of_angles([4 8 12 16]) = list_of_angles([5 9 13 17]) - alfa;
list_of_angles
list_of_angles = list_of_angles .* pi/180;
list_of_angles
fprintf(1, '*******************************\n');
fout = fopen(outfilename, 'w');
%write the header
fprintf(fout, 'resolution_m: %f\n', resolution);
fprintf(fout, 'min_turning_radius_m: %f\n', rmin_m);
fprintf(fout, 'numberofangles: %d\n', numberofangles);
for angleind = 1:numberofangles
fprintf(fout, 'angle:%d %.8f\n', angleind-1, list_of_angles(angleind));
end;
fprintf(fout, 'totalnumberofprimitives: %d\n', totalnumberofprimitives);
% Note, what is shown x,y,theta changes (not absolute numbers) x aligned
% with the heading of the robot, angles are positive and counterclockwise
% Initialize arrays to store acceptable circular primitives before choosing the best among them.
% We only need 3 base sets of primitives for angles 0, alfa and 45 degrees.
primdata = zeros(numberofbaseangles, max_number_of_prims_per_angle, countmax, 8); % startx, starty, starttheta, endx, endy, endtheta, tvoverrv, rv
primcount = zeros(numberofbaseangles, max_number_of_prims_per_angle);
basemprimendpts_c = zeros(numberofbaseangles, numberofprimsperangle, 6); % x_c, y_c, theta_c, costmult, tvoverrv, rv
% Calculate sets of valid primitives with ids 2,3,4 for base angles 0, alfa and 45 degrees.
% Primitives with id=1 (short forward) will be calculated by re-scaling primitives with id=2 (long forward).
for angleind=1:3
for primind=2:4
if (angleind == 1 && primind == 4)
gen_base_prims(angleind, primind, xmin, xmax, -ymax, -ymin);
else
gen_base_prims(angleind, primind, xmin, xmax, ymin, ymax);
end;
end;
end;
fprintf(1, '\n');
fprintf(1, 'find best primitives start:\n');
find_best_prims();
fprintf(1, '\n++++++++++++++++++\n');
fprintf(1, 'start writing primitives to file:\n');
fprintf(1, '\n');
h1f = figure(1);
h1a = axes('parent',h1f);
hold on;
s = 2.0; %0.6;
xxmin = -s;
xxmax = s;
yymin = -s;
yymax = s;
xt = 5*resolution;
yt = 5*resolution;
axis equal;
axis([xxmin xxmax yymin yymax]);
%axis([-0.5 0.5 -0.5 0.5]);
set(gca,'XTick', xxmin:xt:xxmax);
set(gca,'YTick',yymin:yt:yymax);
grid on;
primposes = [];
primsamples = [];
primendangle = [];
% Iterate over angles
for angleind = 1:numberofangles
fprintf(1, '***************\n');
fprintf(1, 'angleind=%d\n', angleind-1);
currentangle = list_of_angles(angleind);
currentangle_36000int = round(currentangle*18000000000/pi);
fprintf(1, '--------------------\n');
fprintf(1, 'currentangle=%f currentangle_36000int=%d\n', currentangle, currentangle_36000int);
numofsamples0 = zeros(numberofprimsperangle);
endPoses_c = zeros(numberofprimsperangle, 3); % x_c, y_c, theta_c
turningradiuses = zeros(numberofprimsperangle);
intermposes_m = [];
intermcells_m_orig = []; %zeros(numofsamples, 3); %x,y,theta
for primind = 1:numberofprimsperangle %number_of_base_prims_per_angle %[1,3,4]
fprintf(1, '+++++++++++++++++++++++++++\n');
fprintf(1, 'primind=%d\n', primind-1);
%compute which template to use
if (rem(currentangle_36000int, 9000000000) == 0)
mprimendpts_c = basemprimendpts_c(1, primind,:);
angle = currentangle;
turning_radius = mprimendpts_c(5);
rvel = mprimendpts_c(6);
fprintf(1, '0000 angle=%f\n', angle);
elseif (rem(currentangle_36000int, 4500000000) == 0)
mprimendpts_c = basemprimendpts_c(3, primind,:);
angle = currentangle - 45*pi/180;
turning_radius = mprimendpts_c(5);
rvel = mprimendpts_c(6);
fprintf(1, '4500 angle=%f\n', angle);
elseif (rem(currentangle_36000int-beta1, 9000000000) == 0) %6400
mprimendpts_c = basemprimendpts_c(2, primind,:);
mprimendpts_c(1) = basemprimendpts_c(2, primind,2); %reeverse x and y
mprimendpts_c(2) = basemprimendpts_c(2, primind,1);
mprimendpts_c(3) = -basemprimendpts_c(2, primind,3); %reverse the angle as well
angle = currentangle - beta*pi/180;
turning_radius = -mprimendpts_c(5);
rvel = -mprimendpts_c(6);
fprintf(1, '90-alfa angle=%f\n', angle);
elseif (rem(currentangle_36000int-alfa1, 9000000000) == 0)
mprimendpts_c = basemprimendpts_c(2, primind,:);
angle = currentangle - alfa*pi/180;
turning_radius = mprimendpts_c(5);
rvel = mprimendpts_c(6);
fprintf(1, 'alfa angle=%f\n', angle);
else
fprintf(1, 'ERROR: invalid angular resolution. angle = %d\n', currentangle_36000int);
return;
end;
[res, turning_radius_center] = generate_intermediate_poses(angleind, primind, currentangle, angle, rvel, turning_radius, mprimendpts_c);
for ii = 1:numofsamples
intermposes_m(primind, ii, :) = [intermcells_m(primind,ii,1)*resolution intermcells_m(primind,ii,2)*resolution intermcells_m(primind,ii,3)]; % x, y, theta
%intermposes_m_orig(primind, iind, :) = [sgn*intermcells_m_orig(iind,1) sgn*intermcells_m_orig(iind,2) intermcells_m(iind,3)]; % x, y, theta
primposes(angleind, primind, ii, :) = intermposes_m(primind, ii, :);
end;
%pause;
end; %for primind = 1:numberofprimsperangle
%output to the mprim file and plot
for primind = 1:numberofprimsperangle
fprintf(fout, 'primID: %d\n', primind-1);
fprintf(fout, 'startangle_c: %d\n', angleind-1);
fprintf(fout, 'endpose_c: %d %d %d\n', endPoses_c(primind,1), endPoses_c(primind,2), endPoses_c(primind,3));
additionalcostmult = costmult(primind);
fprintf(fout, 'additionalactioncostmult: %d\n', additionalcostmult);
fprintf(fout, 'turning_radius: %.4f\n', turningradiuses(primind));
numofsamples = numofsamples0(primind);
fprintf(fout, 'intermediateposes: %d\n', numofsamples);
for interind = 1:numofsamples
fprintf(fout, '%.4f %.4f %.4f\n', intermposes_m(primind,interind,1), intermposes_m(primind,interind,2), intermposes_m(primind,interind,3));
end;
plot(squeeze(intermposes_m(primind, 1:numofsamples, 1)), squeeze(intermposes_m(primind, 1:numofsamples, 2)), 'r');
dl = 0.0;
if (primind == 3)
dl = 0.05;
elseif (primind == 4)
dl = -0.05;
end;
slabel = [int2str(angleind), '-', int2str(primind)];
%text(intermposes_m(primind,numofsamples,1)+dl, intermposes_m(primind,numofsamples,2)+dl, slabel);
end; %primid
%pause;
end; %angleid
%%%%%%%%%%%%%%%%%%%%%%%******************************
fprintf(1, '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n');
fclose('all');
function[] = gen_base_prims(angle_ind, prim_ind, xmin0, xmax0, ymin0, ymax0)
fprintf(1, '\ngen_base_prims: angle_ind=%d prim_ind=%d\n', angle_ind, prim_ind);
angle_incr = prim_angle_increments(prim_ind);
start_theta = list_of_angles(angle_ind);
if (angle_ind == 1 && angle_incr == -1)
end_theta = -list_of_angles(2);
else
end_theta = list_of_angles(angle_ind + angle_incr);
end;
for i=1:imax
count = 0;
if (i == 1)
xmn0 = xmin0;
xmx0 = xmax0;
ymn0 = ymin0;
ymx0 = ymax0;
prm_ind = prim_ind;
else
xmn0 = -xmax0;
xmx0 = -xmin0;
ymn0 = -ymax0;
ymx0 = -ymin0;
prm_ind = prim_ind + number_of_base_prims_per_angle; %4;
end;
basemprimendpts_c(angle_ind, prm_ind, 3) = angle_incr;
fprintf(1, '\nangle_ind=%d prm_ind=%d\n', angle_ind, prm_ind);
fprintf(1, 'start_theta=%f end_theta=%f basemprimendpts_c(3)=%f angle_incr=%d\n', start_theta, end_theta, basemprimendpts_c(angle_ind,prim_ind,3), angle_incr);
%fprintf(1,'xmn0=%f xmx0=%f\n', xmn0,xmx0);
%fprintf(1,'ymn0=%f ymx0=%f\n', ymn0,ymx0);
for endx_c = xmn0:xmx0
for endy_c = ymn0:ymx0
prim_endx_c = endx_c;
prim_endy_c = endy_c;
if (prim_ind == 3 || prim_ind == 4)
R = [sin(end_theta) - sin(start_theta); cos(start_theta) - cos(end_theta)];
RT = R';
B = [prim_endx_c - start_x; prim_endy_c - start_y];
tvoverrv = pinv(RT*R)*RT*B;
if (abs(tvoverrv) < rmin_c)
continue;
end;
rv = end_theta - start_theta;
tv = rv*tvoverrv;
err = abs(R*tvoverrv - B);
errxy = norm(err);
if (errxy < errmin)
fprintf(1, 'count=%d endx_c=%d endy_c=%d errxy=%f tvoverrv=%f rv=%f tv=%f prim_endx_c=%f prim_endy_c=%f\n', count, endx_c, endy_c, errxy, tvoverrv, rv, tv, prim_endx_c, prim_endy_c);
end
else
yy = prim_endx_c*tan(end_theta);
errxy = abs(prim_endy_c - yy);
tvoverrv = sqrt(prim_endx_c*prim_endx_c + yy*yy);
rv = 0.0;
tv = tvoverrv;
% if (errxy < 2*errmin)
% fprintf(1, 'count=%d endx_c=%d endy_c=%d errxy=%f tvoverrv=%f rv=%f tv=%f prim_endx_c=%f prim_endy_c=%f\n', count, endx_c, endy_c, errxy, tvoverrv, rv, tv, prim_endx_c, prim_endy_c);
% end
end;
if (errxy > errmin)
continue;
end;
if (count+1 > countmax)
fprintf(1, 'endy: count = %d, countmax = %d\n', count, countmax);
break;
end;
count = count + 1;
primdata(angle_ind, prm_ind, count, 1) = start_x;
primdata(angle_ind, prm_ind, count, 2) = start_y;
primdata(angle_ind, prm_ind, count, 3) = start_theta;
primdata(angle_ind, prm_ind, count, 4) = prim_endx_c;
primdata(angle_ind, prm_ind, count, 5) = prim_endy_c;
primdata(angle_ind, prm_ind, count, 6) = end_theta;
primdata(angle_ind, prm_ind, count, 7) = tvoverrv;
primdata(angle_ind, prm_ind, count, 8) = rv;
%pause;
end; %for end_y
if (count+1 > countmax)
fprintf(1, 'endx: count = %d, countmax = %d\n', count, countmax);
break;
end;
end; %for end_x
primcount(angle_ind, prm_ind) = count;
fprintf(1, 'count=%f\n', primcount(angle_ind, prm_ind));
end %for i=1:imax
end
function[] = find_best_prims()
% First find the motion primitive for angle_ind = 1 and prim_ind = 4
% with minimal turning radius among selected set of primitives that
% satisfy the given min turning radius and epsilon conditions.
[rmin0, countmin] = min(abs(primdata(1, 4, 1:primcount(1, 4), 7)));
fprintf(1, 'countmin=%f rmin0=%f\n', countmin, rmin0);
%Iterate over all saved motion primitives for all angles and for each
%angle find a set of primitives with turning radius closest to the min radius found above.
rrm = rmin0;
%rrm = 30.0;
%rad = [];
for angle_id=1:numberofbaseangles
fprintf(1, '************* angle_id=%f *********\n', angle_id);
i1 = number_of_base_prims_per_angle + 3; %7;
i2 = number_of_base_prims_per_angle + 4; %8;
for prim_ind = [3,4,i1,i2] %4:-1:3
if (has_backward_prims == 0 && prim_ind > number_of_base_prims_per_angle) %>4
continue;
end
fprintf(1, '------------- prim_ind=%f -----------\n', prim_ind);
% [dmin, countmin] = min(abs(abs(primdata(angle_id, prim_ind, 1:primcount(angle_id, prim_ind), 7)) - rmin0));
% if (angle_id == 1)
% rrm = rmin0;
% elseif (prim_ind == 3)
% rrm = rad(angle_id, 4);
% else
% rrm = rad(angle_id-1, 3);
% end;
fprintf(1, 'rrm=%f\n', rrm);
fprintf(1, 'primcount(angle_id, prim_ind)=%d\n', primcount(angle_id, prim_ind));
[dmin, countmin] = min(abs(abs(primdata(angle_id, prim_ind, 1:primcount(angle_id, prim_ind), 7)) - rrm));
fprintf(1, 'countmin=%f dmin=%f\n', countmin, dmin);
tvoverrv = primdata(angle_id, prim_ind, countmin, 7);
%rad(angle_id, prim_ind) = abs(tvoverrv);
rv = primdata(angle_id, prim_ind, countmin, 6) - primdata(angle_id, prim_ind, countmin, 3);
tv = rv*tvoverrv;
fprintf(1, 'tvoverrv=%f rv=%f tv=%f\n', tvoverrv, rv, tv);
basemprimendpts_c(angle_id, prim_ind, 1) = primdata(angle_id, prim_ind, countmin, 4);
basemprimendpts_c(angle_id, prim_ind, 2) = primdata(angle_id, prim_ind, countmin, 5);
basemprimendpts_c(angle_id, prim_ind, 5) = primdata(angle_id, prim_ind, countmin, 7);
basemprimendpts_c(angle_id, prim_ind, 6) = primdata(angle_id, prim_ind, countmin, 8);
fprintf(1, 'basemprimendpts_c=%f %f %f %f %f %f\n', basemprimendpts_c(angle_id, prim_ind, :)); %x, y, angle_incr, costmult,tvoverrv, rv
end;
for i = 1:imax
%prim_ind = 2; %long forward
prim_ind = 2 + (i-1)*number_of_base_prims_per_angle; %4;
fprintf(1, '------------- prim_ind=%f -----------\n', prim_ind);
i1 = prim_ind+1;
i2 = prim_ind+2;
x = (basemprimendpts_c(angle_id, i1, 1) + basemprimendpts_c(angle_id, i2, 1))/2;
y = (basemprimendpts_c(angle_id, i1, 2) + basemprimendpts_c(angle_id, i2, 2))/2;
fprintf(1, 'x=%f y=%f primcount=%d\n', x, y, primcount(angle_id, prim_ind));
[dmin, countmin] = min(sqrt((primdata(angle_id, prim_ind, 1:primcount(angle_id, prim_ind), 4)-x).^2 + (primdata(angle_id, prim_ind, 1:primcount(angle_id, prim_ind), 5)-y).^2));
fprintf(1, 'angle_id=%d prim_ind=%d countmin=%d dmin=%f\n', angle_id, prim_ind, countmin, dmin);
basemprimendpts_c(angle_id, prim_ind, 1) = primdata(angle_id, prim_ind, countmin, 4);
basemprimendpts_c(angle_id, prim_ind, 2) = primdata(angle_id, prim_ind, countmin, 5);
fprintf(1, 'basemprimendpts_c=%f %f %f %f %f %f\n', basemprimendpts_c(angle_id, prim_ind, :));
%prim_ind = 1; %short forward
i1 = prim_ind;
prim_ind = prim_ind - 1;
fprintf(1, '------------- prim_ind=%f -----------\n', prim_ind);
x = basemprimendpts_c(angle_id, i1, 1);
y = basemprimendpts_c(angle_id, i1, 2);
d = nonzero_min(abs(x), abs(y));
basemprimendpts_c(angle_id, prim_ind, 1) = x/d;
basemprimendpts_c(angle_id, prim_ind, 2) = y/d;
fprintf(1, 'basemprimendpts_c=%f %f %f %f %f %f\n', basemprimendpts_c(angle_id, prim_ind, :));
%prim_ind = 5; %short forward
if (has_turn_in_place_prims == 1)
prim_ind = 5 + (i-1)*number_of_base_prims_per_angle;
fprintf(1, '------------- prim_ind=%f -----------\n', prim_ind);
basemprimendpts_c(angle_id, prim_ind, 1) = 0.0;
basemprimendpts_c(angle_id, prim_ind, 2) = 0.0;
if (prim_ind == 5)
i1 = prim_ind-2;
else
i1 = prim_ind-1;
end;
basemprimendpts_c(angle_id, prim_ind, 3) = basemprimendpts_c(angle_id, i1, 3);
basemprimendpts_c(angle_id, prim_ind, 5) = 0.0;
basemprimendpts_c(angle_id, prim_ind, 6) = basemprimendpts_c(angle_id, i1, 6);
fprintf(1, 'basemprimendpts_c=%f %f %f %f %f %f\n', basemprimendpts_c(angle_id, prim_ind, :));
end
end;
end;
end
%generate intermediate poses (remember they are w.r.t 0,0 (and not centers of the cells)
function[res, turning_radius_center] = generate_intermediate_poses(angleind, primind, currentangle, angle, rvel, turning_radius, mprimendpts_c)
baseendpose_c = mprimendpts_c(1:3);
endtheta_c = rem(angleind - 1 + baseendpose_c(3), numberofangles);
fprintf(1,'\n');
fprintf(1, 'generate_intermediate_poses start\n');
fprintf(1, 'baseendpose_c: %f %f %f endtheta_c=%d\n', baseendpose_c, endtheta_c);
startpt = [0 0 currentangle];
endx_c = round(baseendpose_c(1)*cos(angle) - baseendpose_c(2)*sin(angle));
endy_c = round(baseendpose_c(1)*sin(angle) + baseendpose_c(2)*cos(angle));
if (angleind == 1 && endtheta_c == -1)
end_angle = -list_of_angles(2);
else
end_angle = list_of_angles(endtheta_c + 1);
end;
endpt = [endx_c endy_c end_angle];
dist_m = sqrt(sum((endpt(1:2) - startpt(1:2)).^2));
dist_rad = abs(currentangle - end_angle);
fprintf(1, 'currentangle=%f end_angle=%f\n', currentangle, end_angle);
if (endx_c == 0 && endy_c == 0)
numofsamples = abs(round(dist_rad/interm_spacing_rad));
else
numofsamples = floor(dist_m/interm_spacing_c) + 1;
end;
%numofsamples = 1 + max(round(dist_m/interm_spacing_m), abs(round(dist_rad/interm_spacing_rad)));
fprintf(1, 'endx_c=%f endy_c=%f endtheta_c=%d turning_radius=%f rvel=%f transformation angle=%f end_angle=%f numofsamples=%d dist_m=%f dist_rad=%f\n', endx_c, endy_c, endtheta_c, turning_radius, rvel, angle*180/pi, end_angle, numofsamples, dist_m, dist_rad);
numofsamples0(primind) = numofsamples;
if (baseendpose_c(3) == 0) %move forward/backward
for iind = 1:numofsamples
dt = (iind-1)/(numofsamples-1);
intermcells_m(primind, iind,:) = [startpt(1) + (endpt(1) - startpt(1))*dt ...
startpt(2) + (endpt(2) - startpt(2))*dt ...
rem(startpt(3) + (endpt(3) - startpt(3))*dt, 2*pi)];
end;
res = correct_poses();
turning_radius_center = 0.0;
elseif (endx_c == 0 && endy_c == 0) %turn in place
for iind = 1:numofsamples
dt = (iind-1)/(numofsamples-1);
dtheta = rvel*dt + startpt(3);
intermcells_m(primind, iind,:) = [0.0 0.0 dtheta];
end;
res = correct_poses();
turning_radius_center = 0.0;
else
for iind = 1:numofsamples
dt = (iind-1)/(numofsamples-1);
dtheta = rvel*dt + startpt(3);
x = startpt(1) + turning_radius*(sin(dtheta) - sin(startpt(3)));
y = startpt(2) + turning_radius*(cos(startpt(3)) - cos(dtheta));
intermcells_m(primind, iind,:) = [x y dtheta];
% fprintf(1, 'iind=%d dt=%f x=%f y=%f dtheta=%f %f %f\n', iind, dt, intermcells_m(iind,1), intermcells_m(iind,2), dtheta, x, y);
end;
res = correct_poses();
[turning_radius_center, arc_len_m, turn_angle] = average_turning_radius();
end;
%pause;
k = primind;
endPoses_c(k, :) = [round(endx_c) round(endy_c) round(endtheta_c)];
turningradiuses(k) = turning_radius*resolution;
turningradiuses_center(k) = turning_radius_center;
primsamples(angleind, k) = numofsamples;
primendangle(angleind, k) = endtheta_c;
%pause;
function[turn_rad_aver, arc_len_m, turn_angle] = average_turning_radius()
turn_angle = 0.0;
turn_rad_aver = 0.0;
arc_len_m = 0.0;
for ind = 1:numofsamples
if (ind > 1)
dx = intermcells_m(primind, ind,1) - intermcells_m(primind, ind-1,1);
dy = intermcells_m(primind, ind,2) - intermcells_m(primind, ind-1,2);
ds = sqrt(dx*dx + dy*dy);
dth = (intermcells_m(primind, ind,3) - intermcells_m(primind, ind-1,3));
arc_len_m = arc_len_m + ds;
turn_angle = turn_angle + dth;
turn_rad = ds/dth;
turn_rad_aver = turn_rad_aver + abs(turn_rad);
%fprintf(1, 'ind=%d ds=%f dth=%f turn_rad=%f\n', ind, ds, dth, turn_rad);
end;
end
turn_rad_aver = turn_rad_aver/(numofsamples - 1);
turn_angle = abs(turn_angle);
fprintf('arc_len_m = %f turn_angle = %f turn_rad_aver = %f\n', arc_len_m, turn_angle, turn_rad_aver);
end
%correct intermediate poses using interpolation to place the end point of the motion primitive exactly to the grid node.
function[status] = correct_poses()
status = true;
%error = [endpt(1) - intermcells_m(primind, numofsamples,1) endpt(2) - intermcells_m(primind, numofsamples,2) endpt(3) - intermcells_m(primind, numofsamples,3)];
errx = endpt(1) - intermcells_m(primind, numofsamples,1);
erry = endpt(2) - intermcells_m(primind, numofsamples,2);
errth = endpt(3) - intermcells_m(primind, numofsamples,3);
fprintf(1, '********************\n');
fprintf(1, 'correction:\n');
fprintf(1,'numofsamples = %d\n', numofsamples);
fprintf(1, 'startpt(1)=%f startpt(2)=%f startpt(3)=%f\n', startpt(1), startpt(2), startpt(3));
fprintf(1, 'endpt(1)=%f endpt(2)=%f endpt(3)=%f\n', endpt(1), endpt(2), endpt(3));
fprintf(1, 'mprimendpts_c(1)=%f mprimendpts_c(2)=%f mprimendpts_c(3)=%f\n', mprimendpts_c(1), mprimendpts_c(2), mprimendpts_c(3));
fprintf(1, 'error: dx %f dy %f dtheta %f\n', errx, erry, errth);
R0 = [sin(end_angle) - sin(startpt(3)); cos(startpt(3)) - cos(end_angle)];
RT0 = R0';
B0 = [endpt(1) - start_x; endpt(2) - start_y];
tr = abs(pinv(RT0*R0)*RT0*B0);
fprintf(1, 'tr = %f\n', tr);
if (tr > 0 && tr < rmin_m)
fprintf(1, 'WARNING: After interpolation turning radius is less than the specified min!\n');
status = false;
end;
interpfactor = 0:1/(numofsamples-1):1;
%save original motion for display purposes only
for i=1:numofsamples
intermcells_m_orig(primind, i,1) = intermcells_m(primind, i,1);
intermcells_m_orig(primind, i,2) = intermcells_m(primind, i,2);
intermcells_m_orig(primind, i,3) = intermcells_m(primind, i,3);
end;
%correct intermideate poses using interpolation
for i=1:numofsamples
intermcells_m(primind, i,1) = intermcells_m(primind, i,1) + errx*interpfactor(i);
intermcells_m(primind, i,2) = intermcells_m(primind, i,2) + erry*interpfactor(i);
end;
end
end
function d = nonzero_min(x,y)
if (x == 0)
d = y;
elseif (y == 0)
d = x;
else
d = min(x, y);
end;
end
function[x1,y1,theta1] = rotate(x,y,theta,theta0)
x1 = x * cos(theta0) - y * sin(theta0);
y1 = x * sin(theta0) + y * cos(theta0);
r = [cos(theta/2), 0.0, 0.0, sin(theta/2)];
q = [cos(theta0/2), 0.0, 0.0, sin(theta0/2)];
f(1) = (r(1) * q(1)) - (r(2) * q(2)) - (r(3) * q(3)) - (r(4) * q(4));
f(2) = (r(1) * q(2)) + (r(2) * q(1)) - (r(3) * q(4)) + (r(4) * q(3));
f(3) = (r(1) * q(3)) + (r(2) * q(4)) + (r(3) * q(1)) - (r(4) * q(2));
f(4) = (r(1) * q(4)) - (r(2) * q(3)) + (r(3) * q(2)) + (r(4) * q(1));
theta1 = 2*atan2(f(4), f(1));
end
function[x1,y1,theta1] = rotate_clockwise(x,y,theta,theta0)
r = [cos(theta/2), 0.0, 0.0, sin(theta/2)];
q = [cos(theta0/2), 0.0, 0.0, sin(theta0/2)];
q(4) = -q(4);
theta00 = 2*atan2(q(4), q(1));
x1 = x * cos(theta00) - y * sin(theta00);
y1 = x * sin(theta00) + y * cos(theta00);
f(1) = (r(1) * q(1)) - (r(2) * q(2)) - (r(3) * q(3)) - (r(4) * q(4));
f(2) = (r(1) * q(2)) + (r(2) * q(1)) - (r(3) * q(4)) + (r(4) * q(3));
f(3) = (r(1) * q(3)) + (r(2) * q(4)) + (r(3) * q(1)) - (r(4) * q(2));
f(4) = (r(1) * q(4)) - (r(2) * q(3)) + (r(3) * q(2)) + (r(4) * q(1));
theta1 = 2*atan2(f(4), f(1));
end
function[x1,y1,theta1] = add_origin_and_turn(x,y,theta, x0,y0,theta0)
[x1,y1,theta1] = rotate(x,y,theta,theta0);
x1 = x1 + x0;
y1 = y1 + y0;
end
function[x1,y1,theta1] = remove_origin_and_turn(x,y,theta, x0,y0,theta0)
x2 = x - x0;
y2 = y - y0;
[x1,y1,theta1] = rotate_clockwise(x2,y2,theta,theta0);
end
function[x2,y2,theta2] = transform(x0, y0, theta0, start_theta)
[x1,y1,theta1] = add_origin_and_turn(1.0,0.0,0.0, x0,y0,theta0);
x2 = x1 - cos(start_theta);
y2 = y1 - sin(start_theta);
theta2 = theta1;
end
function[outfilename] = generate_file_name(base_name, res, rmin_m, errmin)
res_s = num2str(res, 2);
res_s = strrep(res_s, '.', '');
rmin_s = num2str(rmin_m, 2);
rmin_s = strrep(rmin_s, '.', '');
err_s = num2str(errmin, 2);
err_s = strrep(err_s, '.', '');
outfilename1 = strcat(base_name, 'res');
outfilename2 = strcat(outfilename1, res_s);
outfilename1 = strcat(outfilename2, '_rad');
outfilename2 = strcat(outfilename1, rmin_s);
outfilename1 = strcat(outfilename2, '_err');
outfilename2 = strcat(outfilename1, err_s);
outfilename = strcat(outfilename2, '.mprim');
end
end

View File

@@ -0,0 +1,286 @@
% /*
% * Copyright (c) 2008, Maxim Likhachev
% * All rights reserved.
% *
% * Redistribution and use in source and binary forms, with or without
% * modification, are permitted provided that the following conditions are met:
% *
% * * Redistributions of source code must retain the above copyright
% * notice, this list of conditions and the following disclaimer.
% * * Redistributions in binary form must reproduce the above copyright
% * notice, this list of conditions and the following disclaimer in the
% * documentation and/or other materials provided with the distribution.
% * * Neither the name of the Carnegie Mellon University nor the names of its
% * contributors may be used to endorse or promote products derived from
% * this software without specific prior written permission.
% *
% * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% * POSSIBILITY OF SUCH DAMAGE.
% */
function[] = genmprim_unicycleplussideways(outfilename)
%
%generates motion primitives and saves them into file
%
%written by Maxim Likhachev
%---------------------------------------------------
%
%defines
UNICYCLE_MPRIM_16DEGS = 1;
if UNICYCLE_MPRIM_16DEGS == 1
resolution = 0.025;
numberofangles = 16; %preferably a power of 2, definitely multiple of 8
numberofprimsperangle = 9;
%multipliers (multiplier is used as costmult*cost)
forwardcostmult = 1;
backwardcostmult = 5;
forwardandturncostmult = 3;
sidestepcostmult = 2;
turninplacecostmult = 1;
%note, what is shown x,y,theta *changes* (that is, dx,dy,dtheta and not absolute numbers)
%0 degreees
basemprimendpts0_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult
%angles are positive counterclockwise
%0 theta change
basemprimendpts0_c(1,:) = [1 0 0 forwardcostmult];
basemprimendpts0_c(2,:) = [8 0 0 forwardcostmult];
basemprimendpts0_c(3,:) = [-1 0 0 backwardcostmult];
%1/16 theta change
basemprimendpts0_c(4,:) = [8 1 1 forwardandturncostmult];
basemprimendpts0_c(5,:) = [8 -1 -1 forwardandturncostmult];
%turn in place
basemprimendpts0_c(6,:) = [0 0 1 turninplacecostmult];
basemprimendpts0_c(7,:) = [0 0 -1 turninplacecostmult];
%sideways maintaining the same heading
basemprimendpts0_c(8,:) = [0 1 0 sidestepcostmult];
basemprimendpts0_c(9,:) = [0 -1 0 sidestepcostmult];
%45 degrees
basemprimendpts45_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%angles are positive counterclockwise
%0 theta change
basemprimendpts45_c(1,:) = [1 1 0 forwardcostmult];
basemprimendpts45_c(2,:) = [6 6 0 forwardcostmult];
basemprimendpts45_c(3,:) = [-1 -1 0 backwardcostmult];
%1/16 theta change
basemprimendpts45_c(4,:) = [5 7 1 forwardandturncostmult];
basemprimendpts45_c(5,:) = [7 5 -1 forwardandturncostmult];
%turn in place
basemprimendpts45_c(6,:) = [0 0 1 turninplacecostmult];
basemprimendpts45_c(7,:) = [0 0 -1 turninplacecostmult];
%sideways maintaining the same heading
basemprimendpts45_c(8,:) = [-1 1 0 sidestepcostmult];
basemprimendpts45_c(9,:) = [1 -1 0 sidestepcostmult];
%22.5 degrees
basemprimendpts22p5_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%angles are positive counterclockwise
%0 theta change
basemprimendpts22p5_c(1,:) = [2 1 0 forwardcostmult];
basemprimendpts22p5_c(2,:) = [6 3 0 forwardcostmult];
basemprimendpts22p5_c(3,:) = [-2 -1 0 backwardcostmult];
%1/16 theta change
basemprimendpts22p5_c(4,:) = [5 4 1 forwardandturncostmult];
basemprimendpts22p5_c(5,:) = [7 2 -1 forwardandturncostmult];
%turn in place
basemprimendpts22p5_c(6,:) = [0 0 1 turninplacecostmult];
basemprimendpts22p5_c(7,:) = [0 0 -1 turninplacecostmult];
%sideways maintaining the same heading
basemprimendpts22p5_c(8,:) = [-1 2 0 sidestepcostmult];
basemprimendpts22p5_c(9,:) = [1 -2 0 sidestepcostmult];
else
fprintf(1, 'ERROR: undefined mprims type\n');
return;
end;
fout = fopen(outfilename, 'w');
%write the header
fprintf(fout, 'resolution_m: %f\n', resolution);
fprintf(fout, 'numberofangles: %d\n', numberofangles);
fprintf(fout, 'totalnumberofprimitives: %d\n', numberofprimsperangle*numberofangles);
%iterate over angles
for angleind = 1:numberofangles
figure(1);
hold off;
text(0, 0, int2str(angleind));
%iterate over primitives
for primind = 1:numberofprimsperangle
fprintf(fout, 'primID: %d\n', primind-1);
fprintf(fout, 'startangle_c: %d\n', angleind-1);
%current angle
currentangle = (angleind-1)*2*pi/numberofangles;
currentangle_36000int = round((angleind-1)*36000/numberofangles);
%compute which template to use
if (rem(currentangle_36000int, 9000) == 0)
basemprimendpts_c = basemprimendpts0_c(primind,:);
angle = currentangle;
fprintf(1, '90\n');
elseif (rem(currentangle_36000int, 4500) == 0)
basemprimendpts_c = basemprimendpts45_c(primind,:);
angle = currentangle - 45*pi/180;
fprintf(1, '45\n');
elseif (rem(currentangle_36000int-7875, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
basemprimendpts_c(1) = basemprimendpts33p75_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts33p75_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts33p75_c(primind, 3); %reverse the angle as well
angle = currentangle - 78.75*pi/180;
fprintf(1, '78p75\n');
elseif (rem(currentangle_36000int-6750, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
basemprimendpts_c(1) = basemprimendpts22p5_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts22p5_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts22p5_c(primind, 3); %reverse the angle as well
%fprintf(1, '%d %d %d onto %d %d %d\n', basemprimendpts22p5_c(1), basemprimendpts22p5_c(2), basemprimendpts22p5_c(3), ...
% basemprimendpts_c(1), basemprimendpts_c(2), basemprimendpts_c(3));
angle = currentangle - 67.5*pi/180;
fprintf(1, '67p5\n');
elseif (rem(currentangle_36000int-5625, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
basemprimendpts_c(1) = basemprimendpts11p25_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts11p25_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts11p25_c(primind, 3); %reverse the angle as well
angle = currentangle - 56.25*pi/180;
fprintf(1, '56p25\n');
elseif (rem(currentangle_36000int-3375, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
angle = currentangle - 33.75*pi/180;
fprintf(1, '33p75\n');
elseif (rem(currentangle_36000int-2250, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
angle = currentangle - 22.5*pi/180;
fprintf(1, '22p5\n');
elseif (rem(currentangle_36000int-1125, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
angle = currentangle - 11.25*pi/180;
fprintf(1, '11p25\n');
else
fprintf(1, 'ERROR: invalid angular resolution. angle = %d\n', currentangle_36000int);
return;
end;
%now figure out what action will be
baseendpose_c = basemprimendpts_c(1:3);
additionalactioncostmult = basemprimendpts_c(4);
endx_c = round(baseendpose_c(1)*cos(angle) - baseendpose_c(2)*sin(angle));
endy_c = round(baseendpose_c(1)*sin(angle) + baseendpose_c(2)*cos(angle));
endtheta_c = rem(angleind - 1 + baseendpose_c(3), numberofangles);
endpose_c = [endx_c endy_c endtheta_c];
fprintf(1, 'rotation angle=%f\n', angle*180/pi);
if baseendpose_c(2) == 0 & baseendpose_c(3) == 0
%fprintf(1, 'endpose=%d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
end;
%generate intermediate poses (remember they are w.r.t 0,0 (and not
%centers of the cells)
numofsamples = 10;
intermcells_m = zeros(numofsamples,3);
if UNICYCLE_MPRIM_16DEGS == 1
startpt = [0 0 currentangle];
endpt = [endpose_c(1)*resolution endpose_c(2)*resolution ...
rem(angleind - 1 + baseendpose_c(3), numberofangles)*2*pi/numberofangles];
intermcells_m = zeros(numofsamples,3);
if ((endx_c == 0 & endy_c == 0) | baseendpose_c(3) == 0) %turn in place or move forward
for iind = 1:numofsamples
intermcells_m(iind,:) = [startpt(1) + (endpt(1) - startpt(1))*(iind-1)/(numofsamples-1) ...
startpt(2) + (endpt(2) - startpt(2))*(iind-1)/(numofsamples-1) ...
0];
rotation_angle = (baseendpose_c(3) ) * (2*pi/numberofangles);
intermcells_m(iind,3) = rem(startpt(3) + (rotation_angle)*(iind-1)/(numofsamples-1), 2*pi);
end;
else %unicycle-based move forward or backward
R = [cos(startpt(3)) sin(endpt(3)) - sin(startpt(3));
sin(startpt(3)) -(cos(endpt(3)) - cos(startpt(3)))];
S = pinv(R)*[endpt(1) - startpt(1); endpt(2) - startpt(2)];
l = S(1);
tvoverrv = S(2);
rv = (baseendpose_c(3)*2*pi/numberofangles + l/tvoverrv);
tv = tvoverrv*rv;
if l < 0
fprintf(1, 'WARNING: l = %d < 0 -> bad action start/end points\n', l);
l = 0;
end;
%compute rv
%rv = baseendpose_c(3)*2*pi/numberofangles;
%compute tv
%tvx = (endpt(1) - startpt(1))*rv/(sin(endpt(3)) - sin(startpt(3)))
%tvy = -(endpt(2) - startpt(2))*rv/(cos(endpt(3)) - cos(startpt(3)))
%tv = (tvx + tvy)/2.0;
%generate samples
for iind = 1:numofsamples
dt = (iind-1)/(numofsamples-1);
%dtheta = rv*dt + startpt(3);
%intermcells_m(iind,:) = [startpt(1) + tv/rv*(sin(dtheta) - sin(startpt(3))) ...
% startpt(2) - tv/rv*(cos(dtheta) - cos(startpt(3))) ...
% dtheta];
if(dt*tv < l)
intermcells_m(iind,:) = [startpt(1) + dt*tv*cos(startpt(3)) ...
startpt(2) + dt*tv*sin(startpt(3)) ...
startpt(3)];
else
dtheta = rv*(dt - l/tv) + startpt(3);
intermcells_m(iind,:) = [startpt(1) + l*cos(startpt(3)) + tvoverrv*(sin(dtheta) - sin(startpt(3))) ...
startpt(2) + l*sin(startpt(3)) - tvoverrv*(cos(dtheta) - cos(startpt(3))) ...
dtheta];
end;
end;
%correct
errorxy = [endpt(1) - intermcells_m(numofsamples,1) ...
endpt(2) - intermcells_m(numofsamples,2)];
fprintf(1, 'l=%f errx=%f erry=%f\n', l, errorxy(1), errorxy(2));
interpfactor = [0:1/(numofsamples-1):1];
intermcells_m(:,1) = intermcells_m(:,1) + errorxy(1)*interpfactor';
intermcells_m(:,2) = intermcells_m(:,2) + errorxy(2)*interpfactor';
end;
end;
%write out
fprintf(fout, 'endpose_c: %d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
fprintf(fout, 'additionalactioncostmult: %d\n', additionalactioncostmult);
fprintf(fout, 'intermediateposes: %d\n', size(intermcells_m,1));
for interind = 1:size(intermcells_m, 1)
fprintf(fout, '%.4f %.4f %.4f\n', intermcells_m(interind,1), intermcells_m(interind,2), intermcells_m(interind,3));
end;
plot(intermcells_m(:,1), intermcells_m(:,2));
axis([-0.3 0.3 -0.3 0.3]);
text(intermcells_m(numofsamples,1), intermcells_m(numofsamples,2), int2str(endpose_c(3)));
hold on;
end;
grid;
pause;
end;
fclose('all');

View File

@@ -0,0 +1,296 @@
% /*
% * Copyright (c) 2008, Maxim Likhachev
% * All rights reserved.
% *
% * Redistribution and use in source and binary forms, with or without
% * modification, are permitted provided that the following conditions are met:
% *
% * * Redistributions of source code must retain the above copyright
% * notice, this list of conditions and the following disclaimer.
% * * Redistributions in binary form must reproduce the above copyright
% * notice, this list of conditions and the following disclaimer in the
% * documentation and/or other materials provided with the distribution.
% * * Neither the name of the Carnegie Mellon University nor the names of its
% * contributors may be used to endorse or promote products derived from
% * this software without specific prior written permission.
% *
% * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% * POSSIBILITY OF SUCH DAMAGE.
% */
function[] = genmprim_unicycleplussidewaysplusbackturn(outfilename)
%
%generates motion primitives and saves them into file
%
%written by Maxim Likhachev
%---------------------------------------------------
%
%defines
UNICYCLE_MPRIM_16DEGS = 1;
if UNICYCLE_MPRIM_16DEGS == 1
resolution = 0.025;
numberofangles = 16; %preferably a power of 2, definitely multiple of 8
numberofprimsperangle = 11;
%multipliers (multiplier is used as costmult*cost)
forwardcostmult = 1;
backwardcostmult = 5;
forwardandturncostmult = 3;
sidestepcostmult = 2;
turninplacecostmult = 1;
%note, what is shown x,y,theta *changes* (that is, dx,dy,dtheta and not absolute numbers)
%0 degreees
basemprimendpts0_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult
%angles are positive counterclockwise
%0 theta change
basemprimendpts0_c(1,:) = [1 0 0 forwardcostmult];
basemprimendpts0_c(2,:) = [8 0 0 forwardcostmult];
basemprimendpts0_c(3,:) = [-1 0 0 backwardcostmult];
%1/16 theta change
basemprimendpts0_c(4,:) = [8 1 1 forwardandturncostmult];
basemprimendpts0_c(5,:) = [8 -1 -1 forwardandturncostmult];
%turn in place
basemprimendpts0_c(6,:) = [0 0 1 turninplacecostmult];
basemprimendpts0_c(7,:) = [0 0 -1 turninplacecostmult];
%sideways maintaining the same heading
basemprimendpts0_c(8,:) = [0 1 0 sidestepcostmult];
basemprimendpts0_c(9,:) = [0 -1 0 sidestepcostmult];
%1/16 theta change going backward
basemprimendpts0_c(10,:) = [-8 -1 1 backwardcostmult];
basemprimendpts0_c(11,:) = [-8 1 -1 backwardcostmult];
%45 degrees
basemprimendpts45_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%angles are positive counterclockwise
%0 theta change
basemprimendpts45_c(1,:) = [1 1 0 forwardcostmult];
basemprimendpts45_c(2,:) = [6 6 0 forwardcostmult];
basemprimendpts45_c(3,:) = [-1 -1 0 backwardcostmult];
%1/16 theta change
basemprimendpts45_c(4,:) = [5 7 1 forwardandturncostmult];
basemprimendpts45_c(5,:) = [7 5 -1 forwardandturncostmult];
%turn in place
basemprimendpts45_c(6,:) = [0 0 1 turninplacecostmult];
basemprimendpts45_c(7,:) = [0 0 -1 turninplacecostmult];
%sideways maintaining the same heading
basemprimendpts45_c(8,:) = [-1 1 0 sidestepcostmult];
basemprimendpts45_c(9,:) = [1 -1 0 sidestepcostmult];
%1/16 theta change going back
basemprimendpts45_c(10,:) = [-5 -7 1 backwardcostmult];
basemprimendpts45_c(11,:) = [-7 -5 -1 backwardcostmult];
%22.5 degrees
basemprimendpts22p5_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%angles are positive counterclockwise
%0 theta change
basemprimendpts22p5_c(1,:) = [2 1 0 forwardcostmult];
basemprimendpts22p5_c(2,:) = [6 3 0 forwardcostmult];
basemprimendpts22p5_c(3,:) = [-2 -1 0 backwardcostmult];
%1/16 theta change
basemprimendpts22p5_c(4,:) = [5 4 1 forwardandturncostmult];
basemprimendpts22p5_c(5,:) = [7 2 -1 forwardandturncostmult];
%turn in place
basemprimendpts22p5_c(6,:) = [0 0 1 turninplacecostmult];
basemprimendpts22p5_c(7,:) = [0 0 -1 turninplacecostmult];
%sideways maintaining the same heading
basemprimendpts22p5_c(8,:) = [-1 2 0 sidestepcostmult];
basemprimendpts22p5_c(9,:) = [1 -2 0 sidestepcostmult];
%1/16 theta change going back
basemprimendpts22p5_c(10,:) = [-5 -4 1 backwardcostmult];
basemprimendpts22p5_c(11,:) = [-7 -2 -1 backwardcostmult];
else
fprintf(1, 'ERROR: undefined mprims type\n');
return;
end;
fout = fopen(outfilename, 'w');
%write the header
fprintf(fout, 'resolution_m: %f\n', resolution);
fprintf(fout, 'numberofangles: %d\n', numberofangles);
fprintf(fout, 'totalnumberofprimitives: %d\n', numberofprimsperangle*numberofangles);
%iterate over angles
for angleind = 1:numberofangles
figure(1);
hold off;
text(0, 0, int2str(angleind));
%iterate over primitives
for primind = 1:numberofprimsperangle
fprintf(fout, 'primID: %d\n', primind-1);
fprintf(fout, 'startangle_c: %d\n', angleind-1);
%current angle
currentangle = (angleind-1)*2*pi/numberofangles;
currentangle_36000int = round((angleind-1)*36000/numberofangles);
%compute which template to use
if (rem(currentangle_36000int, 9000) == 0)
basemprimendpts_c = basemprimendpts0_c(primind,:);
angle = currentangle;
fprintf(1, '90\n');
elseif (rem(currentangle_36000int, 4500) == 0)
basemprimendpts_c = basemprimendpts45_c(primind,:);
angle = currentangle - 45*pi/180;
fprintf(1, '45\n');
elseif (rem(currentangle_36000int-7875, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
basemprimendpts_c(1) = basemprimendpts33p75_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts33p75_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts33p75_c(primind, 3); %reverse the angle as well
angle = currentangle - 78.75*pi/180;
fprintf(1, '78p75\n');
elseif (rem(currentangle_36000int-6750, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
basemprimendpts_c(1) = basemprimendpts22p5_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts22p5_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts22p5_c(primind, 3); %reverse the angle as well
%fprintf(1, '%d %d %d onto %d %d %d\n', basemprimendpts22p5_c(1), basemprimendpts22p5_c(2), basemprimendpts22p5_c(3), ...
% basemprimendpts_c(1), basemprimendpts_c(2), basemprimendpts_c(3));
angle = currentangle - 67.5*pi/180;
fprintf(1, '67p5\n');
elseif (rem(currentangle_36000int-5625, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
basemprimendpts_c(1) = basemprimendpts11p25_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts11p25_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts11p25_c(primind, 3); %reverse the angle as well
angle = currentangle - 56.25*pi/180;
fprintf(1, '56p25\n');
elseif (rem(currentangle_36000int-3375, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
angle = currentangle - 33.75*pi/180;
fprintf(1, '33p75\n');
elseif (rem(currentangle_36000int-2250, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
angle = currentangle - 22.5*pi/180;
fprintf(1, '22p5\n');
elseif (rem(currentangle_36000int-1125, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
angle = currentangle - 11.25*pi/180;
fprintf(1, '11p25\n');
else
fprintf(1, 'ERROR: invalid angular resolution. angle = %d\n', currentangle_36000int);
return;
end;
%now figure out what action will be
baseendpose_c = basemprimendpts_c(1:3);
additionalactioncostmult = basemprimendpts_c(4);
endx_c = round(baseendpose_c(1)*cos(angle) - baseendpose_c(2)*sin(angle));
endy_c = round(baseendpose_c(1)*sin(angle) + baseendpose_c(2)*cos(angle));
endtheta_c = rem(angleind - 1 + baseendpose_c(3), numberofangles);
endpose_c = [endx_c endy_c endtheta_c];
fprintf(1, 'rotation angle=%f\n', angle*180/pi);
if baseendpose_c(2) == 0 & baseendpose_c(3) == 0
%fprintf(1, 'endpose=%d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
end;
%generate intermediate poses (remember they are w.r.t 0,0 (and not
%centers of the cells)
numofsamples = 10;
intermcells_m = zeros(numofsamples,3);
if UNICYCLE_MPRIM_16DEGS == 1
startpt = [0 0 currentangle];
endpt = [endpose_c(1)*resolution endpose_c(2)*resolution ...
rem(angleind - 1 + baseendpose_c(3), numberofangles)*2*pi/numberofangles];
intermcells_m = zeros(numofsamples,3);
if ((endx_c == 0 & endy_c == 0) | baseendpose_c(3) == 0) %turn in place or move forward
for iind = 1:numofsamples
intermcells_m(iind,:) = [startpt(1) + (endpt(1) - startpt(1))*(iind-1)/(numofsamples-1) ...
startpt(2) + (endpt(2) - startpt(2))*(iind-1)/(numofsamples-1) ...
0];
rotation_angle = (baseendpose_c(3) ) * (2*pi/numberofangles);
intermcells_m(iind,3) = rem(startpt(3) + (rotation_angle)*(iind-1)/(numofsamples-1), 2*pi);
end;
else %unicycle-based move forward or backward
R = [cos(startpt(3)) sin(endpt(3)) - sin(startpt(3));
sin(startpt(3)) -(cos(endpt(3)) - cos(startpt(3)))];
S = pinv(R)*[endpt(1) - startpt(1); endpt(2) - startpt(2)];
l = S(1);
tvoverrv = S(2);
rv = (baseendpose_c(3)*2*pi/numberofangles + l/tvoverrv);
tv = tvoverrv*rv;
if ((l < 0 & tv > 0) | (l > 0 & tv < 0))
fprintf(1, 'WARNING: l = %d < 0 -> bad action start/end points\n', l);
l = 0;
end;
%compute rv
%rv = baseendpose_c(3)*2*pi/numberofangles;
%compute tv
%tvx = (endpt(1) - startpt(1))*rv/(sin(endpt(3)) - sin(startpt(3)))
%tvy = -(endpt(2) - startpt(2))*rv/(cos(endpt(3)) - cos(startpt(3)))
%tv = (tvx + tvy)/2.0;
%generate samples
for iind = 1:numofsamples
dt = (iind-1)/(numofsamples-1);
%dtheta = rv*dt + startpt(3);
%intermcells_m(iind,:) = [startpt(1) + tv/rv*(sin(dtheta) - sin(startpt(3))) ...
% startpt(2) - tv/rv*(cos(dtheta) - cos(startpt(3))) ...
% dtheta];
if(abs(dt*tv) < abs(l))
intermcells_m(iind,:) = [startpt(1) + dt*tv*cos(startpt(3)) ...
startpt(2) + dt*tv*sin(startpt(3)) ...
startpt(3)];
else
dtheta = rv*(dt - l/tv) + startpt(3);
intermcells_m(iind,:) = [startpt(1) + l*cos(startpt(3)) + tvoverrv*(sin(dtheta) - sin(startpt(3))) ...
startpt(2) + l*sin(startpt(3)) - tvoverrv*(cos(dtheta) - cos(startpt(3))) ...
dtheta];
end;
end;
%correct
errorxy = [endpt(1) - intermcells_m(numofsamples,1) ...
endpt(2) - intermcells_m(numofsamples,2)];
fprintf(1, 'l=%f errx=%f erry=%f\n', l, errorxy(1), errorxy(2));
interpfactor = [0:1/(numofsamples-1):1];
intermcells_m(:,1) = intermcells_m(:,1) + errorxy(1)*interpfactor';
intermcells_m(:,2) = intermcells_m(:,2) + errorxy(2)*interpfactor';
end;
end;
%write out
fprintf(fout, 'endpose_c: %d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
fprintf(fout, 'additionalactioncostmult: %d\n', additionalactioncostmult);
fprintf(fout, 'intermediateposes: %d\n', size(intermcells_m,1));
for interind = 1:size(intermcells_m, 1)
fprintf(fout, '%.4f %.4f %.4f\n', intermcells_m(interind,1), intermcells_m(interind,2), intermcells_m(interind,3));
end;
plot(intermcells_m(:,1), intermcells_m(:,2));
axis([-0.3 0.3 -0.3 0.3]);
text(intermcells_m(numofsamples,1), intermcells_m(numofsamples,2), int2str(endpose_c(3)));
hold on;
end;
grid;
pause;
end;
fclose('all');

View File

@@ -0,0 +1,306 @@
% /*
% * Copyright (c) 2008, Maxim Likhachev
% * All rights reserved.
% *
% * Redistribution and use in source and binary forms, with or without
% * modification, are permitted provided that the following conditions are met:
% *
% * * Redistributions of source code must retain the above copyright
% * notice, this list of conditions and the following disclaimer.
% * * Redistributions in binary form must reproduce the above copyright
% * notice, this list of conditions and the following disclaimer in the
% * documentation and/or other materials provided with the distribution.
% * * Neither the name of the Carnegie Mellon University nor the names of its
% * contributors may be used to endorse or promote products derived from
% * this software without specific prior written permission.
% *
% * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% * POSSIBILITY OF SUCH DAMAGE.
% */
function[] = genmprim_unicycleplussidewaysplusbackturnplusdiag(outfilename)
%
%generates motion primitives and saves them into file
%
%written by Maxim Likhachev
%---------------------------------------------------
%
%defines
UNICYCLE_MPRIM_16DEGS = 1;
if UNICYCLE_MPRIM_16DEGS == 1
resolution = 0.025;
numberofangles = 16; %preferably a power of 2, definitely multiple of 8
numberofprimsperangle = 13;
%multipliers (multiplier is used as costmult*cost)
forwardcostmult = 1;
backwardcostmult = 1;
forwardandturncostmult = 20; % 3;
sidestepcostmult = 2;
turninplacecostmult = 20;
forwarddiagcostmult = 1; %move forward slightly to the left/right without changing heading
%note, what is shown x,y,theta *changes* (that is, dx,dy,dtheta and not absolute numbers)
%0 degreees
basemprimendpts0_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult
%angles are positive counterclockwise
%0 theta change
basemprimendpts0_c(1,:) = [1 0 0 forwardcostmult];
basemprimendpts0_c(2,:) = [8 0 0 forwardcostmult];
basemprimendpts0_c(3,:) = [-1 0 0 backwardcostmult];
%1/16 theta change
basemprimendpts0_c(4,:) = [8 1 1 forwardandturncostmult];
basemprimendpts0_c(5,:) = [8 -1 -1 forwardandturncostmult];
%turn in place
basemprimendpts0_c(6,:) = [0 0 1 turninplacecostmult];
basemprimendpts0_c(7,:) = [0 0 -1 turninplacecostmult];
%sideways maintaining the same heading
basemprimendpts0_c(8,:) = [0 1 0 sidestepcostmult];
basemprimendpts0_c(9,:) = [0 -1 0 sidestepcostmult];
%1/16 theta change going backward
basemprimendpts0_c(10,:) = [-8 -1 1 backwardcostmult];
basemprimendpts0_c(11,:) = [-8 1 -1 backwardcostmult];
%forward diagonal
basemprimendpts0_c(12,:) = [8 1 0 forwarddiagcostmult];
basemprimendpts0_c(13,:) = [8 -1 0 forwarddiagcostmult];
%45 degrees
basemprimendpts45_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%angles are positive counterclockwise
%0 theta change
basemprimendpts45_c(1,:) = [1 1 0 forwardcostmult];
basemprimendpts45_c(2,:) = [6 6 0 forwardcostmult];
basemprimendpts45_c(3,:) = [-1 -1 0 backwardcostmult];
%1/16 theta change
basemprimendpts45_c(4,:) = [5 7 1 forwardandturncostmult];
basemprimendpts45_c(5,:) = [7 5 -1 forwardandturncostmult];
%turn in place
basemprimendpts45_c(6,:) = [0 0 1 turninplacecostmult];
basemprimendpts45_c(7,:) = [0 0 -1 turninplacecostmult];
%sideways maintaining the same heading
basemprimendpts45_c(8,:) = [-1 1 0 sidestepcostmult];
basemprimendpts45_c(9,:) = [1 -1 0 sidestepcostmult];
%1/16 theta change going back
basemprimendpts45_c(10,:) = [-5 -7 1 backwardcostmult];
basemprimendpts45_c(11,:) = [-7 -5 -1 backwardcostmult];
%forward diagonal
basemprimendpts45_c(12,:) = [5 7 0 forwarddiagcostmult];
basemprimendpts45_c(13,:) = [7 5 0 forwarddiagcostmult];
%22.5 degrees
basemprimendpts22p5_c = zeros(numberofprimsperangle, 4); %x,y,theta,costmult (multiplier is used as costmult*cost)
%angles are positive counterclockwise
%0 theta change
basemprimendpts22p5_c(1,:) = [2 1 0 forwardcostmult];
basemprimendpts22p5_c(2,:) = [6 3 0 forwardcostmult];
basemprimendpts22p5_c(3,:) = [-2 -1 0 backwardcostmult];
%1/16 theta change
basemprimendpts22p5_c(4,:) = [5 4 1 forwardandturncostmult];
basemprimendpts22p5_c(5,:) = [7 2 -1 forwardandturncostmult];
%turn in place
basemprimendpts22p5_c(6,:) = [0 0 1 turninplacecostmult];
basemprimendpts22p5_c(7,:) = [0 0 -1 turninplacecostmult];
%sideways maintaining the same heading
basemprimendpts22p5_c(8,:) = [-1 2 0 sidestepcostmult];
basemprimendpts22p5_c(9,:) = [1 -2 0 sidestepcostmult];
%1/16 theta change going back
basemprimendpts22p5_c(10,:) = [-5 -4 1 backwardcostmult];
basemprimendpts22p5_c(11,:) = [-7 -2 -1 backwardcostmult];
%forward diagonal
basemprimendpts22p5_c(12,:) = [5 4 0 forwarddiagcostmult];
basemprimendpts22p5_c(13,:) = [7 2 0 forwarddiagcostmult];
else
fprintf(1, 'ERROR: undefined mprims type\n');
return;
end;
fout = fopen(outfilename, 'w');
%write the header
fprintf(fout, 'resolution_m: %f\n', resolution);
fprintf(fout, 'numberofangles: %d\n', numberofangles);
fprintf(fout, 'totalnumberofprimitives: %d\n', numberofprimsperangle*numberofangles);
%iterate over angles
for angleind = 1:numberofangles
figure(1);
hold off;
text(0, 0, int2str(angleind));
%iterate over primitives
for primind = 1:numberofprimsperangle
fprintf(fout, 'primID: %d\n', primind-1);
fprintf(fout, 'startangle_c: %d\n', angleind-1);
%current angle
currentangle = (angleind-1)*2*pi/numberofangles;
currentangle_36000int = round((angleind-1)*36000/numberofangles);
%compute which template to use
if (rem(currentangle_36000int, 9000) == 0)
basemprimendpts_c = basemprimendpts0_c(primind,:);
angle = currentangle;
fprintf(1, '90\n');
elseif (rem(currentangle_36000int, 4500) == 0)
basemprimendpts_c = basemprimendpts45_c(primind,:);
angle = currentangle - 45*pi/180;
fprintf(1, '45\n');
elseif (rem(currentangle_36000int-7875, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
basemprimendpts_c(1) = basemprimendpts33p75_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts33p75_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts33p75_c(primind, 3); %reverse the angle as well
angle = currentangle - 78.75*pi/180;
fprintf(1, '78p75\n');
elseif (rem(currentangle_36000int-6750, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
basemprimendpts_c(1) = basemprimendpts22p5_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts22p5_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts22p5_c(primind, 3); %reverse the angle as well
%fprintf(1, '%d %d %d onto %d %d %d\n', basemprimendpts22p5_c(1), basemprimendpts22p5_c(2), basemprimendpts22p5_c(3), ...
% basemprimendpts_c(1), basemprimendpts_c(2), basemprimendpts_c(3));
angle = currentangle - 67.5*pi/180;
fprintf(1, '67p5\n');
elseif (rem(currentangle_36000int-5625, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
basemprimendpts_c(1) = basemprimendpts11p25_c(primind, 2); %reverse x and y
basemprimendpts_c(2) = basemprimendpts11p25_c(primind, 1);
basemprimendpts_c(3) = -basemprimendpts11p25_c(primind, 3); %reverse the angle as well
angle = currentangle - 56.25*pi/180;
fprintf(1, '56p25\n');
elseif (rem(currentangle_36000int-3375, 9000) == 0)
basemprimendpts_c = basemprimendpts33p75_c(primind,:);
angle = currentangle - 33.75*pi/180;
fprintf(1, '33p75\n');
elseif (rem(currentangle_36000int-2250, 9000) == 0)
basemprimendpts_c = basemprimendpts22p5_c(primind,:);
angle = currentangle - 22.5*pi/180;
fprintf(1, '22p5\n');
elseif (rem(currentangle_36000int-1125, 9000) == 0)
basemprimendpts_c = basemprimendpts11p25_c(primind,:);
angle = currentangle - 11.25*pi/180;
fprintf(1, '11p25\n');
else
fprintf(1, 'ERROR: invalid angular resolution. angle = %d\n', currentangle_36000int);
return;
end;
%now figure out what action will be
baseendpose_c = basemprimendpts_c(1:3);
additionalactioncostmult = basemprimendpts_c(4);
endx_c = round(baseendpose_c(1)*cos(angle) - baseendpose_c(2)*sin(angle));
endy_c = round(baseendpose_c(1)*sin(angle) + baseendpose_c(2)*cos(angle));
endtheta_c = rem(angleind - 1 + baseendpose_c(3), numberofangles);
endpose_c = [endx_c endy_c endtheta_c];
fprintf(1, 'rotation angle=%f\n', angle*180/pi);
if baseendpose_c(2) == 0 & baseendpose_c(3) == 0
%fprintf(1, 'endpose=%d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
end;
%generate intermediate poses (remember they are w.r.t 0,0 (and not
%centers of the cells)
numofsamples = 10;
intermcells_m = zeros(numofsamples,3);
if UNICYCLE_MPRIM_16DEGS == 1
startpt = [0 0 currentangle];
endpt = [endpose_c(1)*resolution endpose_c(2)*resolution ...
rem(angleind - 1 + baseendpose_c(3), numberofangles)*2*pi/numberofangles];
intermcells_m = zeros(numofsamples,3);
if ((endx_c == 0 & endy_c == 0) | baseendpose_c(3) == 0) %turn in place or move forward
for iind = 1:numofsamples
intermcells_m(iind,:) = [startpt(1) + (endpt(1) - startpt(1))*(iind-1)/(numofsamples-1) ...
startpt(2) + (endpt(2) - startpt(2))*(iind-1)/(numofsamples-1) ...
0];
rotation_angle = (baseendpose_c(3) ) * (2*pi/numberofangles);
intermcells_m(iind,3) = rem(startpt(3) + (rotation_angle)*(iind-1)/(numofsamples-1), 2*pi);
end;
else %unicycle-based move forward or backward
R = [cos(startpt(3)) sin(endpt(3)) - sin(startpt(3));
sin(startpt(3)) -(cos(endpt(3)) - cos(startpt(3)))];
S = pinv(R)*[endpt(1) - startpt(1); endpt(2) - startpt(2)];
l = S(1);
tvoverrv = S(2);
rv = (baseendpose_c(3)*2*pi/numberofangles + l/tvoverrv);
tv = tvoverrv*rv;
if ((l < 0 & tv > 0) | (l > 0 & tv < 0))
fprintf(1, 'WARNING: l = %d < 0 -> bad action start/end points\n', l);
l = 0;
end;
%compute rv
%rv = baseendpose_c(3)*2*pi/numberofangles;
%compute tv
%tvx = (endpt(1) - startpt(1))*rv/(sin(endpt(3)) - sin(startpt(3)))
%tvy = -(endpt(2) - startpt(2))*rv/(cos(endpt(3)) - cos(startpt(3)))
%tv = (tvx + tvy)/2.0;
%generate samples
for iind = 1:numofsamples
dt = (iind-1)/(numofsamples-1);
%dtheta = rv*dt + startpt(3);
%intermcells_m(iind,:) = [startpt(1) + tv/rv*(sin(dtheta) - sin(startpt(3))) ...
% startpt(2) - tv/rv*(cos(dtheta) - cos(startpt(3))) ...
% dtheta];
if(abs(dt*tv) < abs(l))
intermcells_m(iind,:) = [startpt(1) + dt*tv*cos(startpt(3)) ...
startpt(2) + dt*tv*sin(startpt(3)) ...
startpt(3)];
else
dtheta = rv*(dt - l/tv) + startpt(3);
intermcells_m(iind,:) = [startpt(1) + l*cos(startpt(3)) + tvoverrv*(sin(dtheta) - sin(startpt(3))) ...
startpt(2) + l*sin(startpt(3)) - tvoverrv*(cos(dtheta) - cos(startpt(3))) ...
dtheta];
end;
end;
%correct
errorxy = [endpt(1) - intermcells_m(numofsamples,1) ...
endpt(2) - intermcells_m(numofsamples,2)];
fprintf(1, 'l=%f errx=%f erry=%f\n', l, errorxy(1), errorxy(2));
interpfactor = [0:1/(numofsamples-1):1];
intermcells_m(:,1) = intermcells_m(:,1) + errorxy(1)*interpfactor';
intermcells_m(:,2) = intermcells_m(:,2) + errorxy(2)*interpfactor';
end;
end;
%write out
fprintf(fout, 'endpose_c: %d %d %d\n', endpose_c(1), endpose_c(2), endpose_c(3));
fprintf(fout, 'additionalactioncostmult: %d\n', additionalactioncostmult);
fprintf(fout, 'intermediateposes: %d\n', size(intermcells_m,1));
for interind = 1:size(intermcells_m, 1)
fprintf(fout, '%.4f %.4f %.4f\n', intermcells_m(interind,1), intermcells_m(interind,2), intermcells_m(interind,3));
end;
plot(intermcells_m(:,1), intermcells_m(:,2));
axis([-0.3 0.3 -0.3 0.3]);
text(intermcells_m(numofsamples,1), intermcells_m(numofsamples,2), int2str(endpose_c(3)));
hold on;
end;
grid;
pause;
end;
fclose('all');

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,122 @@
% /*
% * Copyright (c) 2008, Maxim Likhachev
% * All rights reserved.
% *
% * Redistribution and use in source and binary forms, with or without
% * modification, are permitted provided that the following conditions are met:
% *
% * * Redistributions of source code must retain the above copyright
% * notice, this list of conditions and the following disclaimer.
% * * Redistributions in binary form must reproduce the above copyright
% * notice, this list of conditions and the following disclaimer in the
% * documentation and/or other materials provided with the distribution.
% * * Neither the name of the Carnegie Mellon University nor the names of its
% * contributors may be used to endorse or promote products derived from
% * this software without specific prior written permission.
% *
% * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% * POSSIBILITY OF SUCH DAMAGE.
% */
function[] = plot_3Dpath(solfilename, mapfilename, resolution)
%
%Plots a 3D path overlaid on top of the map.
%Resolution should be in meters
%
%written by Maxim Likhachev
%---------------------------------------------------
%
%close all;
obsthresh = 254;
robot_width = 0.6;
robot_length = 1.5;
vehicle = [-robot_length/2.0 -robot_width/2.0
robot_length/2.0 -robot_width/2.0
robot_length/2.0 robot_width/2.0
-robot_length/2.0 robot_width/2.0];
cellsize = resolution;
x = load(solfilename);
%now read in map
fmap = fopen(mapfilename, 'r');
xsize = -1;
ysize = -1;
while(feof(fmap) ~= 1)
s = fscanf(fmap, '%s', 1);
if (strcmp('environment:',s) == 1)
break;
elseif (strcmp('discretization(cells):', s) == 1)
xsize = fscanf(fmap, '%d', 1);
ysize = fscanf(fmap, '%d', 1);
end;
end;
%read the environment itself
fprintf(1, 'reading in map of size %d by %d\n', xsize, ysize);
map = fscanf(fmap, '%d', [xsize, ysize]);
map = map'; %correct matlab loading order
figure(3);
%h = plot(x(:,1),x(:,2), 'k');
%h = plot(x(:,2),size(map,1)*cellsize-x(:,1), 'k');
h = plot(x(:,1),size(map,1)*cellsize-x(:,2), 'k');
set(h,'LineWidth',3);
hold on;
h = text(x(1,1), size(map,1)*cellsize-x(1,2), 'START');
set(h,'LineWidth',5);
h = text(x(size(x,1),1), size(map,1)*cellsize-x(size(x,1),2), 'GOAL');
set(h,'LineWidth',5);
%plot vehicle
%for pind = 1:ceil(length(x)/40):length(x)
for pind = 1:5:length(x)
for i = 1:4
xstartrot = vehicle(i,1)*cos(x(pind,3)) - vehicle(i,2)*sin(x(pind,3)) + x(pind,1);
ystartrot = vehicle(i,1)*sin(x(pind,3)) + vehicle(i,2)*cos(x(pind,3)) + x(pind,2);
if i < 4
xendrot = vehicle(i+1,1)*cos(x(pind,3)) - vehicle(i+1,2)*sin(x(pind,3)) + x(pind,1);;
yendrot = vehicle(i+1,1)*sin(x(pind,3)) + vehicle(i+1,2)*cos(x(pind,3)) + x(pind,2);;
else
xendrot = vehicle(1,1)*cos(x(pind,3)) - vehicle(1,2)*sin(x(pind,3)) + x(pind,1);;
yendrot = vehicle(1,1)*sin(x(pind,3)) + vehicle(1,2)*cos(x(pind,3)) + x(pind,2);;
end;
%%% plot([xstartrot xendrot], [ystartrot yendrot]);
%%% plot([ystartrot yendrot], [size(map,1)*cellsize-xstartrot size(map,1)*cellsize-xendrot]);
plot([xstartrot xendrot], [size(map,1)*cellsize-ystartrot size(map,1)*cellsize-yendrot]);
end;
end;
if 1
for row = 1:size(map,1)
for col = 1:size(map,2)
if(map(row,col) >= obsthresh)
% plot(col*cellsize,row*cellsize,'x');
plot(col*cellsize, (size(map,1)-row)*cellsize,'x');
elseif(map(row,col) > 0)
%plot(col*cellsize, (size(map,1)-row)*cellsize,'.');
end;
end;
end;
end;
%%fplot('2',[6 40 0 5]);
%%fplot('18',[6 40 0 5]);
%%plot(6*ones(length([2:18]),1), [2:18]);
%axis([min(x(:,1))-1 max(x(:,1))+1 min(x(:,2))-1 max(x(:,2))+1]);
%axis([-1 5 -1 5]);

View File

@@ -0,0 +1,15 @@
# - Config file for the sbpl package
# It defines the following variables
# SBPL_INCLUDE_DIRS - include directories for sbpl
# SBPL_LIBRARIES - libraries to link against
get_filename_component(SBPL_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(SBPL_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@")
# Our library dependencies (contains definitions for IMPORTED targets)
if (NOT TARGET sbpl AND NOT sbpl_BINARY_DIR)
include("${SBPL_CMAKE_DIR}/sbpl-targets.cmake")
endif()
# These are IMPORTED targets created by sbpl-targets.cmake
set(SBPL_LIBRARIES sbpl)

View File

@@ -0,0 +1,11 @@
set(PACKAGE_VERSION "@SBPL_VERSION@")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()

View File

@@ -0,0 +1,30 @@
# ===================================================================================
# The SBPL CMake configuration file
#
# ** File generated automatically, do not modify **
#
# Usage from an external project:
# In your CMakeLists.txt, add these lines:
#
# FIND_PACKAGE(sbpl REQUIRED )
# INCLUDE_DIRECTORIES(${SBPL_INCLUDE_DIRS})
# TARGET_LINK_LIBRARIES(MY_TARGET_NAME ${SBPL_LIBRARIES})
#
# This file will define the following variables:
# - SBPL_LIBRARIES : The list of libraries to links against as absolute path
# - SBPL_LIBRARY_DIRS : The directory where lib files are. Calling
# LINK_DIRECTORIES with this path is NOT needed.
# - SBPL_INCLUDE_DIRS : The SBPL include directories.
#
# Based on the example CMake Tutorial
# http://www.vtk.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file
# and OpenCVConfig.cmake.in from OpenCV
# ===================================================================================
set(SBPL_INCLUDE_DIRS "@SBPL_INCLUDE_DIR@")
set(SBPL_LIBRARY_DIRS "@SBPL_LIB_DIR@")
# Set library names as absolute paths:
set(SBPL_LIBRARIES "@SBPL_LIB_DIR@/libsbpl@CMAKE_SHARED_LIBRARY_SUFFIX@")

12
navigations/sbpl/sbpl.pc.in Executable file
View File

@@ -0,0 +1,12 @@
# This file was generated by CMake for @PROJECT_NAME@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@SBPL_LIB_DIR@
includedir=@SBPL_INCLUDE_DIR@
Name: @PKG_NAME@
Description: @PKG_DESC@
Version: @SBPL_VERSION@
Requires: @PKG_EXTERNAL_DEPS@
Libs: -L${libdir} @PKG_SBPL_LIBS@
Cflags: -I${includedir}

View File

@@ -0,0 +1,429 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sbpl/discrete_space_information/environment_XXX.h>
#include <sstream>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/mdp.h>
#include <sbpl/utils/mdpconfig.h>
using namespace std;
//extern clock_t time3_addallout;
//extern clock_t time_gethash;
//extern clock_t time_createhash;
//function prototypes
//-------------------problem specific and local functions---------------------
static unsigned int inthash(unsigned int key)
{
key += (key << 12);
key ^= (key >> 22);
key += (key << 4);
key ^= (key >> 9);
key += (key << 10);
key ^= (key >> 2);
key += (key << 7);
key ^= (key >> 12);
return key;
}
//examples of hash functions: map state coordinates onto a hash value
//#define GETHASHBIN(X, Y) (Y*WIDTH_Y+X)
//here we have state coord: <X1, X2, X3, X4>
unsigned int EnvironmentXXX::GETHASHBIN(unsigned int X1, unsigned int X2, unsigned int X3, unsigned int X4)
{
return inthash((inthash(X1) + (inthash(X2) << 1) + (inthash(X3) << 2) + (inthash(X4) << 3))) &
(EnvXXX.HashTableSize - 1);
}
void EnvironmentXXX::PrintHashTableHist()
{
int s0 = 0, s1 = 0, s50 = 0, s100 = 0, s200 = 0, s300 = 0, slarge = 0;
for (int j = 0; j < (int)EnvXXX.HashTableSize; j++) {
if ((int)EnvXXX.Coord2StateIDHashTable[j].size() == 0)
s0++;
else if ((int)EnvXXX.Coord2StateIDHashTable[j].size() < 50)
s1++;
else if ((int)EnvXXX.Coord2StateIDHashTable[j].size() < 100)
s50++;
else if ((int)EnvXXX.Coord2StateIDHashTable[j].size() < 200)
s100++;
else if ((int)EnvXXX.Coord2StateIDHashTable[j].size() < 300)
s200++;
else if ((int)EnvXXX.Coord2StateIDHashTable[j].size() < 400)
s300++;
else
slarge++;
}
SBPL_PRINTF("hash table histogram: 0:%d, <50:%d, <100:%d, <200:%d, <300:%d, <400:%d >400:%d\n", s0, s1, s50, s100,
s200, s300, slarge);
}
void EnvironmentXXX::ReadConfiguration(FILE* fCfg)
{
//read in the configuration of environment and initialize EnvCfg structure
}
void EnvironmentXXX::InitializeEnvConfig()
{
//aditional to configuration file initialization of EnvCfg if necessary
}
EnvXXXHashEntry_t* EnvironmentXXX::GetHashEntry(unsigned int X1, unsigned int X2, unsigned int X3, unsigned int X4)
{
//clock_t currenttime = clock();
int binid = GETHASHBIN(X1, X2, X3, X4);
#if DEBUG
if ((int)EnvXXX.Coord2StateIDHashTable[binid].size() > 500)
{
SBPL_PRINTF("WARNING: Hash table has a bin %d (X1=%d X2=%d X3=%d X4=%d) of size %d\n",
binid, X1, X2, X3, X4, (int)EnvXXX.Coord2StateIDHashTable[binid].size());
PrintHashTableHist();
}
#endif
//iterate over the states in the bin and select the perfect match
for (int ind = 0; ind < (int)EnvXXX.Coord2StateIDHashTable[binid].size(); ind++) {
if (EnvXXX.Coord2StateIDHashTable[binid][ind]->X1 == X1 &&
EnvXXX.Coord2StateIDHashTable[binid][ind]->X2 == X2 &&
EnvXXX.Coord2StateIDHashTable[binid][ind]->X3 == X3 &&
EnvXXX.Coord2StateIDHashTable[binid][ind]->X4 == X4)
{
//time_gethash += clock()-currenttime;
return EnvXXX.Coord2StateIDHashTable[binid][ind];
}
}
//time_gethash += clock()-currenttime;
return NULL;
}
EnvXXXHashEntry_t* EnvironmentXXX::CreateNewHashEntry(unsigned int X1, unsigned int X2, unsigned int X3,
unsigned int X4)
{
int i;
//clock_t currenttime = clock();
EnvXXXHashEntry_t* HashEntry = new EnvXXXHashEntry_t;
HashEntry->X1 = X1;
HashEntry->X2 = X2;
HashEntry->X3 = X3;
HashEntry->X4 = X4;
HashEntry->stateID = EnvXXX.StateID2CoordTable.size();
//insert into the tables
EnvXXX.StateID2CoordTable.push_back(HashEntry);
//get the hash table bin
i = GETHASHBIN(HashEntry->X1, HashEntry->X2, HashEntry->X3, HashEntry->X4);
//insert the entry into the bin
EnvXXX.Coord2StateIDHashTable[i].push_back(HashEntry);
//insert into and initialize the mappings
int* entry = new int[NUMOFINDICES_STATEID2IND];
StateID2IndexMapping.push_back(entry);
for (i = 0; i < NUMOFINDICES_STATEID2IND; i++) {
StateID2IndexMapping[HashEntry->stateID][i] = -1;
}
if (HashEntry->stateID != (int)StateID2IndexMapping.size() - 1) {
throw SBPL_Exception("ERROR in Env... function: last state has incorrect stateID");
}
//time_createhash += clock()-currenttime;
return HashEntry;
}
void EnvironmentXXX::CreateStartandGoalStates()
{
EnvXXXHashEntry_t* HashEntry;
//create start state
unsigned int X1 = 0;
unsigned int X2 = 0;
unsigned int X3 = 0;
unsigned int X4 = 0;
HashEntry = CreateNewHashEntry(X1, X2, X3, X4);
EnvXXX.startstateid = HashEntry->stateID;
//create goal state
X1 = X2 = X3 = X4 = 1;
HashEntry = CreateNewHashEntry(X1, X2, X3, X4);
EnvXXX.goalstateid = HashEntry->stateID;
}
void EnvironmentXXX::InitializeEnvironment()
{
//initialize the map from Coord to StateID
EnvXXX.HashTableSize = 32 * 1024; //should be power of two
EnvXXX.Coord2StateIDHashTable = new vector<EnvXXXHashEntry_t*> [EnvXXX.HashTableSize];
//initialize the map from StateID to Coord
EnvXXX.StateID2CoordTable.clear();
//create start and goal states
CreateStartandGoalStates();
}
void EnvironmentXXX::AddAllOutcomes(unsigned int SourceX1, unsigned int SourceX2, unsigned int SourceX3,
unsigned int SourceX4, CMDPACTION* action, int cost)
{
EnvXXXHashEntry_t* OutHashEntry;
int i;
float CumProb = 0.0;
//iterate over outcomes
for (i = 0; i < 2; i++) {
unsigned int newX1 = SourceX1 + i;
unsigned int newX2 = SourceX2 + i;
unsigned int newX3 = SourceX3 + i;
unsigned int newX4 = SourceX4 + i;
//add the outcome
if ((OutHashEntry = GetHashEntry(newX1, newX2, newX3, newX4)) == NULL) {
//have to create a new entry
OutHashEntry = CreateNewHashEntry(newX1, newX2, newX3, newX4);
}
float Prob = 0.5; //probability of the outcome
action->AddOutcome(OutHashEntry->stateID, cost, Prob);
CumProb += Prob;
} //while
if (CumProb != 1.0) {
std::stringstream ss("ERROR in EnvXXX... function: prob. of all action outcomes=");
ss << CumProb;
throw SBPL_Exception(ss.str());
}
}
//------------------------------------------------------------------------------
//------------------------------Heuristic computation--------------------------
void EnvironmentXXX::ComputeHeuristicValues()
{
//whatever necessary pre-computation of heuristic values is done here
SBPL_PRINTF("Precomputing heuristics\n");
SBPL_PRINTF("done\n");
}
//-----------interface with outside functions-----------------------------------
bool EnvironmentXXX::InitializeEnv(const char* sEnvFile)
{
FILE* fCfg = fopen(sEnvFile, "r");
if (fCfg == NULL) {
std::stringstream ss("ERROR: unable to open ");
ss << sEnvFile;
throw SBPL_Exception(ss.str());
}
ReadConfiguration(fCfg);
fclose(fCfg);
//Initialize other parameters of the environment
InitializeEnvConfig();
//initialize Environment
InitializeEnvironment();
//pre-compute heuristics
ComputeHeuristicValues();
return true;
}
bool EnvironmentXXX::InitializeMDPCfg(MDPConfig *MDPCfg)
{
//initialize MDPCfg with the start and goal ids
MDPCfg->goalstateid = EnvXXX.goalstateid;
MDPCfg->startstateid = EnvXXX.startstateid;
return true;
}
int EnvironmentXXX::GetFromToHeuristic(int FromStateID, int ToStateID)
{
#if USE_HEUR==0
return 0;
#endif
#if DEBUG
if(FromStateID >= (int)EnvXXX.StateID2CoordTable.size() ||
ToStateID >= (int)EnvXXX.StateID2CoordTable.size())
{
throw SBPL_Exception("ERROR in EnvXXX... function: stateID illegal");
}
#endif
//define this function if it is used in the planner
throw SBPL_Exception("ERROR in EnvXXX.. function: FromToHeuristic is undefined");
return 0;
}
int EnvironmentXXX::GetGoalHeuristic(int stateID)
{
#if USE_HEUR==0
return 0;
#endif
#if DEBUG
if (stateID >= (int)EnvXXX.StateID2CoordTable.size()) {
throw SBPL_Exception("ERROR in EnvXXX... function: stateID illegal");
}
#endif
//define this function if it used in the planner (heuristic forward search would use it)
throw SBPL_Exception("ERROR in EnvXXX.. function: GetGoalHeuristic is undefined");
}
int EnvironmentXXX::GetStartHeuristic(int stateID)
{
#if USE_HEUR==0
return 0;
#endif
#if DEBUG
if (stateID >= (int)EnvXXX.StateID2CoordTable.size()) {
throw SBPL_Exception("ERROR in EnvXXX... function: stateID illegal");
}
#endif
//define this function if it used in the planner (heuristic backward search would use it)
throw SBPL_Exception("ERROR in EnvXXX.. function: GetStartHeuristic is undefined");
return 0;
}
void EnvironmentXXX::SetAllActionsandAllOutcomes(CMDPSTATE* state)
{
#if DEBUG
if (state->StateID >= (int)EnvXXX.StateID2CoordTable.size()) {
throw SBPL_Exception("ERROR in EnvXXX... function: stateID illegal");
}
if ((int)state->Actions.size() != 0) {
throw SBPL_Exception("ERROR in Env_setAllActionsandAllOutcomes: actions already exist for the state");
}
#endif
//if it is goal then no successors
if (state->StateID == EnvXXX.goalstateid) return;
//get values for the state
EnvXXXHashEntry_t* HashEntry = EnvXXX.StateID2CoordTable[state->StateID];
//iterate through the actions for the state
for (int aind = 0; aind < XXX_MAXACTIONSWIDTH; aind++) {
int cost = 1;
//Add Action
CMDPACTION* action = state->AddAction(aind);
//clock_t currenttime = clock();
//add all the outcomes to the action
AddAllOutcomes(HashEntry->X1, HashEntry->X2, HashEntry->X3, HashEntry->X4, action, cost);
//you can break if the number of actual actions is smaller than the maximum possible
//time3_addallout += clock()-currenttime;
}
}
void EnvironmentXXX::SetAllPreds(CMDPSTATE* state)
{
//implement this if the planner needs access to predecessors
throw SBPL_Exception("ERROR in EnvXXX... function: SetAllPreds is undefined");
}
void EnvironmentXXX::GetSuccs(int SourceStateID, vector<int>* SuccIDV, vector<int>* CostV)
{
throw SBPL_Exception("ERROR in EnvXXX... function: GetSuccs is undefined");
}
void EnvironmentXXX::GetPreds(int TargetStateID, vector<int>* PredIDV, vector<int>* CostV)
{
throw SBPL_Exception("ERROR in EnvXXX... function: GetPreds is undefined");
}
int EnvironmentXXX::SizeofCreatedEnv()
{
return (int)EnvXXX.StateID2CoordTable.size();
}
void EnvironmentXXX::PrintState(int stateID, bool bVerbose, FILE* fOut /*=NULL*/)
{
#if DEBUG
if(stateID >= (int)EnvXXX.StateID2CoordTable.size())
{
throw SBPL_Exception("ERROR in EnvXXX... function: stateID illegal (2)");
}
#endif
if (fOut == NULL) fOut = stdout;
EnvXXXHashEntry_t* HashEntry = EnvXXX.StateID2CoordTable[stateID];
if (stateID == EnvXXX.goalstateid) {
SBPL_FPRINTF(fOut, "the state is a goal state\n");
}
SBPL_FPRINTF(fOut, "X1=%d X2=%d X3=%d X4=%d\n", HashEntry->X1, HashEntry->X2, HashEntry->X3, HashEntry->X4);
}
void EnvironmentXXX::PrintEnv_Config(FILE* fOut)
{
//implement this if the planner needs to print out EnvXXX. configuration
throw SBPL_Exception("ERROR in EnvXXX... function: PrintEnv_Config is undefined");
}
//------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,710 @@
/*
* Copyright (c) 2009, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <sbpl/discrete_space_information/environment_nav2Duu.h>
#include <sbpl/utils/mdp.h>
#include <sbpl/utils/mdpconfig.h>
using namespace std;
//extern clock_t time3_addallout;
//extern clock_t time_gethash;
//extern clock_t time_createhash;
#define NAV2DUU_ERR_EPS 0.00001
//function prototypes
//-------------------constructors---------------------
EnvironmentNAV2DUU::EnvironmentNAV2DUU()
{
EnvNAV2DUU.bInitialized = false;
}
//-----------------------------------------------------
//-------------------problem specific and local functions---------------------
void EnvironmentNAV2DUU::ReadConfiguration(FILE* fCfg)
{
//read in the configuration of environment and initialize EnvCfg structure
char sTemp[1024], sTemp1[1024];
//int dTemp;
int x, y;
float fTemp;
//discretization(cells)
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
strcpy(sTemp1, "discretization(cells):");
if (strcmp(sTemp1, sTemp) != 0) {
std::stringstream ss("ERROR: configuration file has incorrect format. Expected ");
ss << sTemp1 << " got " << sTemp;
throw SBPL_Exception(ss.str());
}
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
EnvNAV2DUUCfg.EnvWidth_c = atoi(sTemp);
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
EnvNAV2DUUCfg.EnvHeight_c = atoi(sTemp);
//obsthresh:
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
strcpy(sTemp1, "obsthresh:");
if (strcmp(sTemp1, sTemp) != 0) {
std::stringstream ss("ERROR: configuration file has incorrect format. Expected ");
ss << sTemp1 << " got " << sTemp;
throw SBPL_Exception(ss.str());
}
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
EnvNAV2DUUCfg.obsthresh = (int)(atof(sTemp));
//start(cells):
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
EnvNAV2DUUCfg.StartX_c = atoi(sTemp);
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
EnvNAV2DUUCfg.StartY_c = atoi(sTemp);
if (EnvNAV2DUUCfg.StartX_c < 0 || EnvNAV2DUUCfg.StartX_c >= EnvNAV2DUUCfg.EnvWidth_c) {
throw SBPL_Exception("ERROR: illegal start coordinates");
}
if (EnvNAV2DUUCfg.StartY_c < 0 || EnvNAV2DUUCfg.StartY_c >= EnvNAV2DUUCfg.EnvHeight_c) {
throw SBPL_Exception("ERROR: illegal start coordinates");
}
//end(cells):
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
EnvNAV2DUUCfg.EndX_c = atoi(sTemp);
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
EnvNAV2DUUCfg.EndY_c = atoi(sTemp);
if (EnvNAV2DUUCfg.EndX_c < 0 || EnvNAV2DUUCfg.EndX_c >= EnvNAV2DUUCfg.EnvWidth_c) {
throw SBPL_Exception("ERROR: illegal end coordinates");
}
if (EnvNAV2DUUCfg.EndY_c < 0 || EnvNAV2DUUCfg.EndY_c >= EnvNAV2DUUCfg.EnvHeight_c) {
throw SBPL_Exception("ERROR: illegal end coordinates");
}
//allocate the 2D environment and corresponding uncertainty matrix
EnvNAV2DUUCfg.Grid2D = new unsigned char*[EnvNAV2DUUCfg.EnvWidth_c];
EnvNAV2DUUCfg.UncertaintyGrid2D = new float*[EnvNAV2DUUCfg.EnvWidth_c];
for (x = 0; x < EnvNAV2DUUCfg.EnvWidth_c; x++) {
EnvNAV2DUUCfg.Grid2D[x] = new unsigned char[EnvNAV2DUUCfg.EnvHeight_c];
EnvNAV2DUUCfg.UncertaintyGrid2D[x] = new float[EnvNAV2DUUCfg.EnvHeight_c];
}
//environment:
EnvNAV2DUUCfg.sizeofH = 0;
if (fscanf(fCfg, "%s", sTemp) != 1) {
throw SBPL_Exception("ERROR: ran out of env file early");
}
for (y = 0; y < EnvNAV2DUUCfg.EnvHeight_c; y++)
for (x = 0; x < EnvNAV2DUUCfg.EnvWidth_c; x++) {
if (fscanf(fCfg, "%f", &fTemp) != 1) {
throw SBPL_Exception("ERROR: incorrect format of config file");
}
if (fTemp > 1.0 - NAV2DUU_ERR_EPS || fTemp < NAV2DUU_ERR_EPS) {
//we assume that the value is just a cost
EnvNAV2DUUCfg.Grid2D[x][y] = (int)fTemp;
if (EnvNAV2DUUCfg.Grid2D[x][y] >= EnvNAV2DUUCfg.obsthresh)
EnvNAV2DUUCfg.UncertaintyGrid2D[x][y] = 1.0;
else
EnvNAV2DUUCfg.UncertaintyGrid2D[x][y] = 0.0;
}
else {
//the value is probability of being free
EnvNAV2DUUCfg.Grid2D[x][y] = 0; //assume cost is 0 if traversable
EnvNAV2DUUCfg.UncertaintyGrid2D[x][y] = fTemp;
EnvNAV2DUUCfg.sizeofH++;
}
}
EnvNAV2DUUCfg.sizeofS = this->EnvNAV2DUUCfg.EnvWidth_c * this->EnvNAV2DUUCfg.EnvHeight_c;
SBPL_PRINTF("total size of environment=%d, number of unknown cells=%d\n", EnvNAV2DUUCfg.sizeofS,
EnvNAV2DUUCfg.sizeofH);
}
//mapdata and uncertaintymapdata is assumed to be organized into a linear array with y being major: map[x+y*width]
void EnvironmentNAV2DUU::SetConfiguration(int width, int height, const unsigned char* mapdata,
const float* uncertaintymapdata)
{
EnvNAV2DUUCfg.EnvWidth_c = width;
EnvNAV2DUUCfg.EnvHeight_c = height;
int x, y;
//set start and goal to zeros for now
EnvNAV2DUUCfg.StartX_c = 0;
EnvNAV2DUUCfg.StartY_c = 0;
EnvNAV2DUUCfg.EndX_c = 0;
EnvNAV2DUUCfg.EndY_c = 0;
//environment:
//allocate the 2D environment and corresponding uncertainty matrix
EnvNAV2DUUCfg.Grid2D = new unsigned char*[EnvNAV2DUUCfg.EnvWidth_c];
EnvNAV2DUUCfg.UncertaintyGrid2D = new float*[EnvNAV2DUUCfg.EnvWidth_c];
for (x = 0; x < EnvNAV2DUUCfg.EnvWidth_c; x++) {
EnvNAV2DUUCfg.Grid2D[x] = new unsigned char[EnvNAV2DUUCfg.EnvHeight_c];
EnvNAV2DUUCfg.UncertaintyGrid2D[x] = new float[EnvNAV2DUUCfg.EnvHeight_c];
}
//initialize the mape
EnvNAV2DUUCfg.sizeofH = 0;
for (y = 0; y < EnvNAV2DUUCfg.EnvHeight_c; y++) {
for (x = 0; x < EnvNAV2DUUCfg.EnvWidth_c; x++) {
if (mapdata == NULL) {
//special case - all is traversable
EnvNAV2DUUCfg.Grid2D[x][y] = 0;
EnvNAV2DUUCfg.UncertaintyGrid2D[x][y] = 0;
}
else {
EnvNAV2DUUCfg.Grid2D[x][y] = mapdata[x + y * width];
EnvNAV2DUUCfg.UncertaintyGrid2D[x][y] = uncertaintymapdata[x + y * width];
if (EnvNAV2DUUCfg.UncertaintyGrid2D[x][y] >= NAV2DUU_ERR_EPS && EnvNAV2DUUCfg.UncertaintyGrid2D[x][y]
<= (1.0 - NAV2DUU_ERR_EPS)) EnvNAV2DUUCfg.sizeofH++;
}
}
}
EnvNAV2DUUCfg.sizeofS = this->EnvNAV2DUUCfg.EnvWidth_c * this->EnvNAV2DUUCfg.EnvHeight_c;
SBPL_PRINTF("total size of environment=%d, number of unknown cells=%d\n", EnvNAV2DUUCfg.sizeofS,
EnvNAV2DUUCfg.sizeofH);
}
void EnvironmentNAV2DUU::InitializeEnvironment()
{
//initialize goal/start IDs
EnvNAV2DUU.startstateid = ENVNAV2DUU_XYTOSTATEID(EnvNAV2DUUCfg.StartX_c, EnvNAV2DUUCfg.StartY_c);
EnvNAV2DUU.goalstateid = ENVNAV2DUU_XYTOSTATEID(EnvNAV2DUUCfg.EndX_c, EnvNAV2DUUCfg.EndY_c);
//environment initialized
EnvNAV2DUU.bInitialized = true;
}
void EnvironmentNAV2DUU::InitializeEnvConfig()
{
//aditional to configuration file initialization if necessary
Computedxy();
//compute IDs of hidden variables
int x, y;
int idcount = 0;
EnvNAV2DUUCfg.HiddenVariableXY2ID = new int*[EnvNAV2DUUCfg.EnvWidth_c];
for (x = 0; x < EnvNAV2DUUCfg.EnvWidth_c; x++) {
EnvNAV2DUUCfg.HiddenVariableXY2ID[x] = new int[EnvNAV2DUUCfg.EnvHeight_c];
for (y = 0; y < EnvNAV2DUUCfg.EnvWidth_c; y++) {
if (EnvNAV2DUUCfg.UncertaintyGrid2D[x][y] >= NAV2DUU_ERR_EPS && EnvNAV2DUUCfg.UncertaintyGrid2D[x][y]
<= (1.0 - NAV2DUU_ERR_EPS)) {
EnvNAV2DUUCfg.HiddenVariableXY2ID[x][y] = idcount;
idcount++;
}
else
EnvNAV2DUUCfg.HiddenVariableXY2ID[x][y] = -1;
}
}
if (idcount != EnvNAV2DUUCfg.sizeofH) {
throw SBPL_Exception("ERROR: idcount not equal to sizeofH");
}
}
int EnvironmentNAV2DUU::SizeofCreatedEnv()
{
return EnvNAV2DUUCfg.sizeofS;
}
int EnvironmentNAV2DUU::SizeofH()
{
return EnvNAV2DUUCfg.sizeofH;
}
bool EnvironmentNAV2DUU::IsValidRobotPosition(int X, int Y)
{
return (X >= 0 && X < EnvNAV2DUUCfg.EnvWidth_c && Y >= 0 && Y < EnvNAV2DUUCfg.EnvHeight_c &&
EnvNAV2DUUCfg.Grid2D[X][Y] < EnvNAV2DUUCfg.obsthresh &&
EnvNAV2DUUCfg.UncertaintyGrid2D[X][Y] < NAV2DUU_ERR_EPS);
}
bool EnvironmentNAV2DUU::IsWithinMapCell(int X, int Y)
{
return (X >= 0 && X < EnvNAV2DUUCfg.EnvWidth_c && Y >= 0 && Y < EnvNAV2DUUCfg.EnvHeight_c);
}
void EnvironmentNAV2DUU::Computedxy()
{
//initialize some constants for 2D search
EnvNAV2DUUCfg.dx_[0] = 1;
EnvNAV2DUUCfg.dy_[0] = 1;
EnvNAV2DUUCfg.dxintersects_[0][0] = 0;
EnvNAV2DUUCfg.dyintersects_[0][0] = 1;
EnvNAV2DUUCfg.dxintersects_[0][1] = 1;
EnvNAV2DUUCfg.dyintersects_[0][1] = 0;
EnvNAV2DUUCfg.dx_[1] = 1;
EnvNAV2DUUCfg.dy_[1] = 0;
EnvNAV2DUUCfg.dxintersects_[1][0] = 0;
EnvNAV2DUUCfg.dyintersects_[1][0] = 0;
EnvNAV2DUUCfg.dxintersects_[1][1] = 0;
EnvNAV2DUUCfg.dyintersects_[1][1] = 0;
EnvNAV2DUUCfg.dx_[2] = 1;
EnvNAV2DUUCfg.dy_[2] = -1;
EnvNAV2DUUCfg.dxintersects_[2][0] = 0;
EnvNAV2DUUCfg.dyintersects_[2][0] = -1;
EnvNAV2DUUCfg.dxintersects_[2][1] = 1;
EnvNAV2DUUCfg.dyintersects_[2][1] = 0;
EnvNAV2DUUCfg.dx_[3] = 0;
EnvNAV2DUUCfg.dy_[3] = 1;
EnvNAV2DUUCfg.dxintersects_[3][0] = 0;
EnvNAV2DUUCfg.dyintersects_[3][0] = 0;
EnvNAV2DUUCfg.dxintersects_[3][1] = 0;
EnvNAV2DUUCfg.dyintersects_[3][1] = 0;
EnvNAV2DUUCfg.dx_[4] = 0;
EnvNAV2DUUCfg.dy_[4] = -1;
EnvNAV2DUUCfg.dxintersects_[4][0] = 0;
EnvNAV2DUUCfg.dyintersects_[4][0] = 0;
EnvNAV2DUUCfg.dxintersects_[4][1] = 0;
EnvNAV2DUUCfg.dyintersects_[4][1] = 0;
EnvNAV2DUUCfg.dx_[5] = -1;
EnvNAV2DUUCfg.dy_[5] = 1;
EnvNAV2DUUCfg.dxintersects_[5][0] = 0;
EnvNAV2DUUCfg.dyintersects_[5][0] = 1;
EnvNAV2DUUCfg.dxintersects_[5][1] = -1;
EnvNAV2DUUCfg.dyintersects_[5][1] = 0;
EnvNAV2DUUCfg.dx_[6] = -1;
EnvNAV2DUUCfg.dy_[6] = 0;
EnvNAV2DUUCfg.dxintersects_[6][0] = 0;
EnvNAV2DUUCfg.dyintersects_[6][0] = 0;
EnvNAV2DUUCfg.dxintersects_[6][1] = 0;
EnvNAV2DUUCfg.dyintersects_[6][1] = 0;
EnvNAV2DUUCfg.dx_[7] = -1;
EnvNAV2DUUCfg.dy_[7] = -1;
EnvNAV2DUUCfg.dxintersects_[7][0] = 0;
EnvNAV2DUUCfg.dyintersects_[7][0] = -1;
EnvNAV2DUUCfg.dxintersects_[7][1] = -1;
EnvNAV2DUUCfg.dyintersects_[7][1] = 0;
//compute distances
for (int dind = 0; dind < ENVNAV2DUU_MAXDIRS; dind++) {
if (EnvNAV2DUUCfg.dx_[dind] != 0 && EnvNAV2DUUCfg.dy_[dind] != 0) {
if (dind <= 7) {
//the cost of a diagonal move in millimeters
EnvNAV2DUUCfg.dxy_distance_mm_[dind] = (int)(ENVNAV2DUU_COSTMULT * 1.414);
}
else {
//the cost of a move to 1,2 or 2,1 or so on in millimeters
EnvNAV2DUUCfg.dxy_distance_mm_[dind] = (int)(ENVNAV2DUU_COSTMULT * 2.236);
}
}
else
EnvNAV2DUUCfg.dxy_distance_mm_[dind] = ENVNAV2DUU_COSTMULT; //the cost of a horizontal move in millimeters
}
}
/*
void EnvironmentNAV2DUU::ComputeReversedxy()
{
int revaind;
//iterate over actions
for (int aind = 0; aind < NAVLSENV_ROBOTNAVACTIONSWIDTH; aind++)
{
//get the cell location and reverse it
int dX = -EnvNAVLSCfg.dXY[aind][0];
int dY = -EnvNAVLSCfg.dXY[aind][1];
//find the index that corresponds to these offsets
for (revaind = 0; revaind < NAVLSENV_ROBOTNAVACTIONSWIDTH; revaind++)
{
if(EnvNAVLSCfg.dXY[revaind][0] == dX && EnvNAVLSCfg.dXY[revaind][1] == dY)
{
EnvNAVLSCfg.reversedXY[aind] = revaind;
break;
}
}
if(revaind == NAVLSENV_ROBOTNAVACTIONSWIDTH)
{
SBPL_ERROR("ERROR: can not determine a reversed index for aind=%d (dX=%d dY=%d)\n",
aind, EnvNAVLSCfg.dXY[aind][0], EnvNAVLSCfg.dXY[aind][1]);
}
}
}
*/
//------------------------------------------------------------------------------
//------------------------------Heuristic computation--------------------------
void EnvironmentNAV2DUU::ComputeHeuristicValues()
{
//whatever necessary pre-computation of heuristic values is done here
SBPL_PRINTF("Precomputing heuristics\n");
SBPL_PRINTF("done\n");
}
//------------------------------------------------------------------------------
//-----------------Printing Routines--------------------------------------------
void EnvironmentNAV2DUU::PrintState(int stateID, bool bVerbose, FILE* fOut /*=NULL*/)
{
#if DEBUG
if (stateID >= this->EnvNAV2DUUCfg.EnvWidth_c*this->EnvNAV2DUUCfg.EnvHeight_c) {
throw SBPL_Exception("ERROR in EnvNAV2DUU... function: st ateID illegal (2)");
}
#endif
if (fOut == NULL) fOut = stdout;
if (stateID == EnvNAV2DUU.goalstateid && bVerbose) {
SBPL_FPRINTF(fOut, "the state is a goal state\n");
}
if (bVerbose)
SBPL_FPRINTF(fOut, "X=%d Y=%d\n", ENVNAV2DUU_STATEIDTOX(stateID), ENVNAV2DUU_STATEIDTOY(stateID));
else
SBPL_FPRINTF(fOut, "%d %d\n", ENVNAV2DUU_STATEIDTOX(stateID), ENVNAV2DUU_STATEIDTOY(stateID));
}
void EnvironmentNAV2DUU::PrintEnv_Config(FILE* fOut)
{
//implement this if the planner needs to print out EnvNAV2DUU. configuration
throw SBPL_Exception("ERROR in EnvNAV2DUU... function: PrintEnv_Config is undefined");
}
//-------------------------------------------------------------------------------
//-----------interface with outside functions-----------------------------------
bool EnvironmentNAV2DUU::InitializeEnv(const char* sEnvFile)
{
FILE* fCfg = fopen(sEnvFile, "r");
if (fCfg == NULL) {
std::stringstream ss("ERROR: unable to open ");
ss << sEnvFile;
throw SBPL_Exception(ss.str());
}
ReadConfiguration(fCfg);
fclose(fCfg);
InitGeneral();
return true;
}
bool EnvironmentNAV2DUU::InitializeEnv(int width, int height, const unsigned char* mapdata,
const float* uncertaintymapdata, unsigned char obsthresh)
{
SBPL_PRINTF("env: initialized with width=%d height=%d, obsthresh=%d\n", width, height, obsthresh);
EnvNAV2DUUCfg.obsthresh = obsthresh;
SetConfiguration(width, height, mapdata, uncertaintymapdata);
InitGeneral();
return true;
}
bool EnvironmentNAV2DUU::InitGeneral()
{
//initialize other variables in Cfg
InitializeEnvConfig();
//initialize Environment
InitializeEnvironment();
//pre-compute heuristics
ComputeHeuristicValues();
return true;
}
bool EnvironmentNAV2DUU::InitializeMDPCfg(MDPConfig *MDPCfg)
{
//initialize MDPCfg with the start and goal ids
MDPCfg->goalstateid = EnvNAV2DUU.goalstateid;
MDPCfg->startstateid = EnvNAV2DUU.startstateid;
return true;
}
int EnvironmentNAV2DUU::GetFromToHeuristic(int FromStateID, int ToStateID)
{
#if USE_HEUR==0
return 0;
#endif
//define this function if it is used in the planner
throw SBPL_Exception("ERROR in EnvNAV2DUU.. function: FromToHeuristic is undefined");
return 0;
}
int EnvironmentNAV2DUU::GetGoalHeuristic(int stateID)
{
#if USE_HEUR==0
return 0;
#endif
//define this function if it used in the planner (heuristic forward search would use it)
throw SBPL_Exception("ERROR in EnvNAV2DUU..function: GetGoalHeuristic is undefined");
}
int EnvironmentNAV2DUU::GetStartHeuristic(int stateID)
{
#if USE_HEUR==0
return 0;
#endif
//define this function if it used in the planner (heuristic backward search would use it)
throw SBPL_Exception("ERROR in EnvNAV2DUU.. function: GetStartHeuristic is undefined");
return 0;
}
void EnvironmentNAV2DUU::GetPreds(int stateID, const vector<sbpl_BinaryHiddenVar_t>* updatedhvaluesV,
vector<CMDPACTION>* IncomingDetActionV, vector<CMDPACTION>* IncomingStochActionV,
vector<sbpl_BinaryHiddenVar_t>* StochActionNonpreferredOutcomeV)
{
int aind;
//get state coords
int destx = ENVNAV2DUU_STATEIDTOX(stateID);
int desty = ENVNAV2DUU_STATEIDTOY(stateID);
//clear succs
IncomingDetActionV->clear();
IncomingStochActionV->clear();
StochActionNonpreferredOutcomeV->clear();
//check that the destination is valid
if (!IsWithinMapCell(destx, desty) || EnvNAV2DUUCfg.Grid2D[destx][desty] >= EnvNAV2DUUCfg.obsthresh) return;
//see if the destination was originally uncertain
bool bDet = false;
//no need to worry about ==1.0 since obstacles are rejected above
if (EnvNAV2DUUCfg.UncertaintyGrid2D[destx][desty] < NAV2DUU_ERR_EPS)
bDet = true;
//if yes, then figure out the probability of being an obstacle
float ProbObs = EnvNAV2DUUCfg.UncertaintyGrid2D[destx][desty];
int desth_ID = EnvNAV2DUUCfg.HiddenVariableXY2ID[destx][desty];
bool bFreeh = false;
//iterate over updated h-values to make sure dest cell is not in there
for (int hind = 0; hind < (int)updatedhvaluesV->size(); hind++) {
if (updatedhvaluesV->at(hind).Prob < NAV2DUU_ERR_EPS) bFreeh = true; //there are elements that are free
if (updatedhvaluesV->at(hind).h_ID == desth_ID) {
ProbObs = updatedhvaluesV->at(hind).Prob; //found
}
}
//if now known to be an obstacle, then no preds
if (ProbObs > 1.0 - NAV2DUU_ERR_EPS)
return;
else if (ProbObs < NAV2DUU_ERR_EPS) bDet = false; //now it is a deterministic cell
//get the destination costmult
int destcostmult = EnvNAV2DUUCfg.Grid2D[destx][desty];
#if DEBUG
if (EnvNAV2DUUCfg.numofdirs > 8) {
throw SBPL_Exception("ERROR: number of directions can not exceed 8 for now");
}
#endif
//iterate over neighbors
for (aind = 0; aind < EnvNAV2DUUCfg.numofdirs; aind++) {
//the actions are undirected, so we can use the same array of actions as in getsuccs case
int predX = destx + EnvNAV2DUUCfg.dx_[aind];
int predY = desty + EnvNAV2DUUCfg.dy_[aind];
//skip the invalid cells
if (!IsWithinMapCell(predX, predY) || EnvNAV2DUUCfg.Grid2D[predX][predY] >= EnvNAV2DUUCfg.obsthresh) continue;
//running costmult
int costmult = destcostmult;
//get the costmultiplier of pred and update total costmult
costmult = __max(costmult, EnvNAV2DUUCfg.Grid2D[predX][predY]);
//if diagonal move
if (predX != destx && predY != desty) {
//check intersecting cells to make sure they are not uncertain
if (EnvNAV2DUUCfg.UncertaintyGrid2D[destx][predY] >= NAV2DUU_ERR_EPS) {
if (!bFreeh) continue;
//check that it is not known to be free. Otherwise - invalid move
int tempID = EnvNAV2DUUCfg.HiddenVariableXY2ID[destx][predY];
bool btempfree = false;
for (int hind = 0; hind < (int)updatedhvaluesV->size(); hind++) {
if (updatedhvaluesV->at(hind).h_ID == tempID) {
if (updatedhvaluesV->at(hind).Prob < NAV2DUU_ERR_EPS) {
btempfree = true;
break;
}
}
}
if (!btempfree) continue;
}
if (EnvNAV2DUUCfg.UncertaintyGrid2D[predX][desty] >= NAV2DUU_ERR_EPS) {
if (!bFreeh) continue;
//check that it is not known to be free. Otherwise - invalid move
int tempID = EnvNAV2DUUCfg.HiddenVariableXY2ID[predX][desty];
bool btempfree = false;
for (int hind = 0; hind < (int)updatedhvaluesV->size(); hind++) {
if (updatedhvaluesV->at(hind).h_ID == tempID) {
if (updatedhvaluesV->at(hind).Prob < NAV2DUU_ERR_EPS) {
btempfree = true;
break;
}
}
}
if (!btempfree) continue;
}
//compute the costmultiplier of intersect cells and update total costmult
costmult = __max(costmult, EnvNAV2DUUCfg.Grid2D[destx][predY]);
costmult = __max(costmult, EnvNAV2DUUCfg.Grid2D[predX][desty]);
}
//make sure cost is still valid
if (costmult >= EnvNAV2DUUCfg.obsthresh) continue;
//otherwise compute the actual cost (once again we use the fact that
//actions are undirected to determine the cost)
int cost = (((int)costmult) + 1) * EnvNAV2DUUCfg.dxy_distance_mm_[aind];
//create action
int predstateID = ENVNAV2DUU_XYTOSTATEID(predX, predY);
CMDPACTION action(aind, predstateID); //TODO-use reverseindex
if (bDet) {
//if dest is known - then form a deterministic action
action.AddOutcome(stateID, cost, 1.0);
IncomingDetActionV->push_back(action);
}
else {
//if dest is unknown - then form a stoch action and compute the corresponding belief part
action.AddOutcome(stateID, cost, 1 - ProbObs); //preferred outcome
action.AddOutcome(predstateID, 2 * cost, ProbObs); //non-preferred outcome (stateID is untraversable)
IncomingStochActionV->push_back(action);
//also insert the corresponding hidden variable value
sbpl_BinaryHiddenVar_t hval;
hval.h_ID = desth_ID;
hval.Prob = 1; //known to be an obstacle
StochActionNonpreferredOutcomeV->push_back(hval);
}
}
}
//returns the stateid if success, and -1 otherwise
int EnvironmentNAV2DUU::SetGoal(int x, int y)
{
if (!IsWithinMapCell(x, y)) {
SBPL_ERROR("ERROR: trying to set a goal cell %d %d that is outside of map\n", x, y);
return -1;
}
if (!IsValidRobotPosition(x, y)) {
SBPL_PRINTF("WARNING: goal cell is invalid\n");
}
EnvNAV2DUU.goalstateid = ENVNAV2DUU_XYTOSTATEID(x, y);
EnvNAV2DUUCfg.EndX_c = x;
EnvNAV2DUUCfg.EndY_c = y;
return EnvNAV2DUU.goalstateid;
}
//returns the stateid if success, and -1 otherwise
int EnvironmentNAV2DUU::SetStart(int x, int y)
{
if (!IsWithinMapCell(x, y)) {
SBPL_ERROR("ERROR: trying to set a start cell %d %d that is outside of map\n", x, y);
return -1;
}
if (!IsValidRobotPosition(x, y)) {
SBPL_PRINTF("WARNING: start cell is invalid\n");
}
EnvNAV2DUU.startstateid = ENVNAV2DUU_XYTOSTATEID(x, y);
EnvNAV2DUUCfg.StartX_c = x;
EnvNAV2DUUCfg.StartY_c = y;
return EnvNAV2DUU.startstateid;
}
bool EnvironmentNAV2DUU::UpdateCost(int x, int y, unsigned char newcost)
{
EnvNAV2DUUCfg.Grid2D[x][y] = newcost;
return true;
}
//------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,482 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdio>
#include <ctime>
#include <sbpl/discrete_space_information/environment_navxythetamlevlat.h>
#include <sbpl/utils/key.h>
using namespace std;
#if TIME_DEBUG
static clock_t time3_addallout = 0;
static clock_t time_gethash = 0;
static clock_t time_createhash = 0;
static clock_t time_getsuccs = 0;
#endif
static long int checks = 0;
//-----------------constructors/destructors-------------------------------
EnvironmentNAVXYTHETAMLEVLAT::EnvironmentNAVXYTHETAMLEVLAT()
{
numofadditionalzlevs = 0; //by default there is only base level, no additional levels
AddLevelFootprintPolygonV = NULL;
AdditionalInfoinActionsV = NULL;
AddLevelGrid2D = NULL;
AddLevel_cost_possibly_circumscribed_thresh = NULL;
AddLevel_cost_inscribed_thresh = NULL;
}
EnvironmentNAVXYTHETAMLEVLAT::~EnvironmentNAVXYTHETAMLEVLAT()
{
if (AddLevelFootprintPolygonV != NULL) {
delete[] AddLevelFootprintPolygonV;
AddLevelFootprintPolygonV = NULL;
}
if (AdditionalInfoinActionsV != NULL) {
for (int tind = 0; tind < EnvNAVXYTHETALATCfg.NumThetaDirs; tind++) {
for (int aind = 0; aind < EnvNAVXYTHETALATCfg.actionwidth; aind++) {
delete[] AdditionalInfoinActionsV[tind][aind].intersectingcellsV;
}
delete[] AdditionalInfoinActionsV[tind];
}
delete[] AdditionalInfoinActionsV;
AdditionalInfoinActionsV = NULL;
}
if (AddLevelGrid2D != NULL) {
for (int levelind = 0; levelind < numofadditionalzlevs; levelind++) {
for (int xind = 0; xind < EnvNAVXYTHETALATCfg.EnvWidth_c; xind++) {
delete[] AddLevelGrid2D[levelind][xind];
}
delete[] AddLevelGrid2D[levelind];
}
delete[] AddLevelGrid2D;
AddLevelGrid2D = NULL;
}
if (AddLevel_cost_possibly_circumscribed_thresh != NULL) {
delete[] AddLevel_cost_possibly_circumscribed_thresh;
AddLevel_cost_possibly_circumscribed_thresh = NULL;
}
if (AddLevel_cost_inscribed_thresh != NULL) {
delete[] AddLevel_cost_inscribed_thresh;
AddLevel_cost_inscribed_thresh = NULL;
}
//reset the number of additional levels
numofadditionalzlevs = 0;
}
//---------------------------------------------------------------------
//-------------------problem specific and local functions---------------------
//returns true if cell is traversable and within map limits - it checks against all levels including the base one
bool EnvironmentNAVXYTHETAMLEVLAT::IsValidCell(int X, int Y)
{
int levelind;
if (!EnvironmentNAVXYTHETALAT::IsValidCell(X, Y)) return false;
//iterate through the additional levels
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
if (AddLevelGrid2D[levelind][X][Y] >= EnvNAVXYTHETALATCfg.obsthresh) return false;
}
//otherwise the cell is valid at all levels
return true;
}
// returns true if cell is traversable and within map limits for a particular level
bool EnvironmentNAVXYTHETAMLEVLAT::IsValidCell(int X, int Y, int levind)
{
return (X >= 0 && X < EnvNAVXYTHETALATCfg.EnvWidth_c && Y >= 0 && Y < EnvNAVXYTHETALATCfg.EnvHeight_c && levind <
numofadditionalzlevs && AddLevelGrid2D[levind][X][Y] < EnvNAVXYTHETALATCfg.obsthresh);
}
//returns true if cell is untraversable at all levels
bool EnvironmentNAVXYTHETAMLEVLAT::IsObstacle(int X, int Y)
{
int levelind;
if (EnvironmentNAVXYTHETALAT::IsObstacle(X, Y)) return true;
//iterate through the additional levels
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
if (AddLevelGrid2D[levelind][X][Y] >= EnvNAVXYTHETALATCfg.obsthresh) return true;
}
//otherwise the cell is obstacle-free at all cells
return false;
}
//returns true if cell is untraversable in level # levelnum. If levelnum = -1, then it checks all levels
bool EnvironmentNAVXYTHETAMLEVLAT::IsObstacle(int X, int Y, int levind)
{
#if DEBUG
if(levind >= numofadditionalzlevs)
{
SBPL_ERROR("ERROR: IsObstacle invoked at level %d\n", levind);
SBPL_FPRINTF(fDeb, "ERROR: IsObstacle invoked at level %d\n", levind);
return false;
}
#endif
return (AddLevelGrid2D[levind][X][Y] >= EnvNAVXYTHETALATCfg.obsthresh);
}
// returns the maximum over all levels of the cost corresponding to the cell <x,y>
unsigned char EnvironmentNAVXYTHETAMLEVLAT::GetMapCost(int X, int Y)
{
unsigned char mapcost = EnvNAVXYTHETALATCfg.Grid2D[X][Y];
for (int levind = 0; levind < numofadditionalzlevs; levind++) {
mapcost = __max(mapcost, AddLevelGrid2D[levind][X][Y]);
}
return mapcost;
}
// returns the cost corresponding to the cell <x,y> at level levind
unsigned char EnvironmentNAVXYTHETAMLEVLAT::GetMapCost(int X, int Y, int levind)
{
#if DEBUG
if(levind >= numofadditionalzlevs)
{
SBPL_ERROR("ERROR: GetMapCost invoked at level %d\n", levind);
SBPL_FPRINTF(fDeb, "ERROR: GetMapCost invoked at level %d\n", levind);
return false;
}
#endif
return AddLevelGrid2D[levind][X][Y];
}
//returns false if robot intersects obstacles or lies outside of the map.
bool EnvironmentNAVXYTHETAMLEVLAT::IsValidConfiguration(int X, int Y, int Theta)
{
//check the base footprint first
if (!EnvironmentNAVXYTHETALAT::IsValidConfiguration(X, Y, Theta)) return false;
//check the remaining levels now
vector<sbpl_2Dcell_t> footprint;
sbpl_xy_theta_pt_t pose;
//compute continuous pose
pose.x = DISCXY2CONT(X, EnvNAVXYTHETALATCfg.cellsize_m);
pose.y = DISCXY2CONT(Y, EnvNAVXYTHETALATCfg.cellsize_m);
pose.theta = DiscTheta2Cont(Theta, EnvNAVXYTHETALATCfg.NumThetaDirs);
//iterate over additional levels
for (int levind = 0; levind < numofadditionalzlevs; levind++) {
//compute footprint cells
footprint.clear();
get_2d_footprint_cells(AddLevelFootprintPolygonV[levind], &footprint, pose, EnvNAVXYTHETALATCfg.cellsize_m);
//iterate over all footprint cells
for (int find = 0; find < (int)footprint.size(); find++) {
int x = footprint.at(find).x;
int y = footprint.at(find).y;
if (x < 0 || x >= EnvNAVXYTHETALATCfg.EnvWidth_c || y < 0 || y >= EnvNAVXYTHETALATCfg.EnvHeight_c
|| AddLevelGrid2D[levind][x][y] >= EnvNAVXYTHETALATCfg.obsthresh) {
return false;
}
}
}
return true;
}
int EnvironmentNAVXYTHETAMLEVLAT::GetActionCost(int SourceX, int SourceY, int SourceTheta,
EnvNAVXYTHETALATAction_t* action)
{
int basecost = EnvironmentNAVXYTHETALAT::GetActionCost(SourceX, SourceY, SourceTheta, action);
if (basecost >= INFINITECOST) return INFINITECOST;
int addcost = GetActionCostacrossAddLevels(SourceX, SourceY, SourceTheta, action);
return __max(basecost, addcost);
}
int EnvironmentNAVXYTHETAMLEVLAT::GetActionCostacrossAddLevels(int SourceX, int SourceY, int SourceTheta,
EnvNAVXYTHETALATAction_t* action)
{
sbpl_2Dcell_t cell;
sbpl_xy_theta_cell_t interm3Dcell;
int i, levelind = -1;
if (!IsValidCell(SourceX, SourceY)) return INFINITECOST;
if (!IsValidCell(SourceX + action->dX, SourceY + action->dY)) return INFINITECOST;
//case of no levels
if (numofadditionalzlevs == 0) return 0;
//iterate through the additional levels
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
if (AddLevelGrid2D[levelind][SourceX + action->dX][SourceY + action->dY]
>= AddLevel_cost_inscribed_thresh[levelind]) return INFINITECOST;
}
//need to iterate over discretized center cells and compute cost based on them
unsigned char maxcellcost = 0;
unsigned char* maxcellcostateachlevel = new unsigned char[numofadditionalzlevs];
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
maxcellcostateachlevel[levelind] = 0;
}
for (i = 0; i < (int)action->interm3DcellsV.size() && maxcellcost < EnvNAVXYTHETALATCfg.obsthresh; i++) {
interm3Dcell = action->interm3DcellsV.at(i);
interm3Dcell.x = interm3Dcell.x + SourceX;
interm3Dcell.y = interm3Dcell.y + SourceY;
if (interm3Dcell.x < 0 || interm3Dcell.x >= EnvNAVXYTHETALATCfg.EnvWidth_c || interm3Dcell.y < 0 ||
interm3Dcell.y >= EnvNAVXYTHETALATCfg.EnvHeight_c)
{
maxcellcost = EnvNAVXYTHETALATCfg.obsthresh;
break;
}
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
maxcellcost = __max(maxcellcost, AddLevelGrid2D[levelind][interm3Dcell.x][interm3Dcell.y]);
maxcellcostateachlevel[levelind] = __max(maxcellcostateachlevel[levelind],
AddLevelGrid2D[levelind][interm3Dcell.x][interm3Dcell.y]);
//check that the robot is NOT in the cell at which there is no valid orientation
if (maxcellcostateachlevel[levelind] >= AddLevel_cost_inscribed_thresh[levelind]) {
maxcellcost = EnvNAVXYTHETALATCfg.obsthresh;
maxcellcostateachlevel[levelind] = EnvNAVXYTHETALATCfg.obsthresh;
break;
}
}
}
//check collisions that for the particular footprint orientation along the action
for (levelind = 0; levelind < numofadditionalzlevs && (int)maxcellcost < EnvNAVXYTHETALATCfg.obsthresh;
levelind++)
{
if (AddLevelFootprintPolygonV[levelind].size() > 1 && (int)maxcellcostateachlevel[levelind] >=
AddLevel_cost_possibly_circumscribed_thresh[levelind])
{
checks++;
//get intersecting cells for this level
vector<sbpl_2Dcell_t>* intersectingcellsV =
&AdditionalInfoinActionsV[(unsigned int)action->starttheta][action->aind].intersectingcellsV[levelind];
for (i = 0; i < (int)intersectingcellsV->size(); i++) {
//get the cell in the map
cell = intersectingcellsV->at(i);
cell.x = cell.x + SourceX;
cell.y = cell.y + SourceY;
//check validity
if (!IsValidCell(cell.x, cell.y, levelind)) {
maxcellcost = EnvNAVXYTHETALATCfg.obsthresh;
break;
}
//if(AddLevelGrid2D[levelind][cell.x][cell.y] > maxcellcost)
////cost computation changed: cost = max(cost of centers of
//the robot along action)
// maxcellcost = AddLevelGrid2D[levelind][cell.x][cell.y];
// //intersecting cells are only used for collision checking
}
}
}
//no need to max it with grid2D to ensure consistency of h2D since it is done for the base class
//clean up
delete[] maxcellcostateachlevel;
if (maxcellcost >= EnvNAVXYTHETALATCfg.obsthresh)
return INFINITECOST;
else
return action->cost * (((int)maxcellcost) + 1); //use cell cost as multiplicative factor
}
//---------------------------------------------------------------------
//------------debugging functions---------------------------------------------
//-----------------------------------------------------------------------------
//-----------interface with outside functions-----------------------------------
/*
initialization of additional levels. 0 is the original one. All additional ones will start with index 1
*/
bool EnvironmentNAVXYTHETAMLEVLAT::InitializeAdditionalLevels(int numofadditionalzlevs_in,
const vector<sbpl_2Dpt_t>* perimeterptsV,
unsigned char* cost_inscribed_thresh_in,
unsigned char* cost_possibly_circumscribed_thresh_in)
{
int levelind = -1, xind = -1, yind = -1;
sbpl_xy_theta_pt_t temppose;
temppose.x = 0.0;
temppose.y = 0.0;
temppose.theta = 0.0;
vector<sbpl_2Dcell_t> footprint;
numofadditionalzlevs = numofadditionalzlevs_in;
SBPL_PRINTF("Planning with additional z levels. Number of additional z levels = %d\n", numofadditionalzlevs);
//allocate memory and set FootprintPolygons for additional levels
AddLevelFootprintPolygonV = new vector<sbpl_2Dpt_t> [numofadditionalzlevs];
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
AddLevelFootprintPolygonV[levelind] = perimeterptsV[levelind];
}
//print out the size of a footprint for each additional level
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
footprint.clear();
get_2d_footprint_cells(AddLevelFootprintPolygonV[levelind], &footprint, temppose,
EnvNAVXYTHETALATCfg.cellsize_m);
SBPL_PRINTF("number of cells in footprint for additional level %d = %d\n", levelind,
(unsigned int)footprint.size());
}
//compute additional levels action info
SBPL_PRINTF("pre-computing action data for additional levels:\n");
AdditionalInfoinActionsV = new EnvNAVXYTHETAMLEVLATAddInfoAction_t*[EnvNAVXYTHETALATCfg.NumThetaDirs];
for (int tind = 0; tind < EnvNAVXYTHETALATCfg.NumThetaDirs; tind++) {
SBPL_PRINTF("pre-computing for angle %d out of %d angles\n", tind, EnvNAVXYTHETALATCfg.NumThetaDirs);
//compute sourcepose
sbpl_xy_theta_pt_t sourcepose;
sourcepose.x = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
sourcepose.y = DISCXY2CONT(0, EnvNAVXYTHETALATCfg.cellsize_m);
sourcepose.theta = DiscTheta2Cont(tind, EnvNAVXYTHETALATCfg.NumThetaDirs);
AdditionalInfoinActionsV[tind] = new EnvNAVXYTHETAMLEVLATAddInfoAction_t[EnvNAVXYTHETALATCfg.actionwidth];
//iterate over actions for each angle
for (int aind = 0; aind < EnvNAVXYTHETALATCfg.actionwidth; aind++) {
EnvNAVXYTHETALATAction_t* nav3daction = &EnvNAVXYTHETALATCfg.ActionsV[tind][aind];
//initialize delta variables
AdditionalInfoinActionsV[tind][aind].dX = nav3daction->dX;
AdditionalInfoinActionsV[tind][aind].dY = nav3daction->dY;
AdditionalInfoinActionsV[tind][aind].starttheta = tind;
AdditionalInfoinActionsV[tind][aind].endtheta = nav3daction->endtheta;
//finally, create the footprint for the action for each level
AdditionalInfoinActionsV[tind][aind].intersectingcellsV = new vector<sbpl_2Dcell_t> [numofadditionalzlevs];
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
get_2d_motion_cells(AddLevelFootprintPolygonV[levelind],
EnvNAVXYTHETALATCfg.ActionsV[tind][aind].intermptV,
&AdditionalInfoinActionsV[tind][aind].intersectingcellsV[levelind],
EnvNAVXYTHETALATCfg.cellsize_m);
}
}
}
//create maps for additional levels and initialize to zeros (freespace)
AddLevelGrid2D = new unsigned char**[numofadditionalzlevs];
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
AddLevelGrid2D[levelind] = new unsigned char*[EnvNAVXYTHETALATCfg.EnvWidth_c];
for (xind = 0; xind < EnvNAVXYTHETALATCfg.EnvWidth_c; xind++) {
AddLevelGrid2D[levelind][xind] = new unsigned char[EnvNAVXYTHETALATCfg.EnvHeight_c];
for (yind = 0; yind < EnvNAVXYTHETALATCfg.EnvHeight_c; yind++) {
AddLevelGrid2D[levelind][xind][yind] = 0;
}
}
}
//create inscribed and circumscribed cost thresholds
AddLevel_cost_possibly_circumscribed_thresh = new unsigned char[numofadditionalzlevs];
AddLevel_cost_inscribed_thresh = new unsigned char[numofadditionalzlevs];
for (levelind = 0; levelind < numofadditionalzlevs; levelind++) {
AddLevel_cost_possibly_circumscribed_thresh[levelind] = cost_possibly_circumscribed_thresh_in[levelind];
AddLevel_cost_inscribed_thresh[levelind] = cost_inscribed_thresh_in[levelind];
}
return true;
}
//set 2D map for the additional level levind
bool EnvironmentNAVXYTHETAMLEVLAT::Set2DMapforAddLev(const unsigned char* mapdata, int levind)
{
int xind = -1, yind = -1;
if (AddLevelGrid2D == NULL) {
SBPL_ERROR("ERROR: failed to set2Dmap because the map was not allocated previously\n");
return false;
}
for (xind = 0; xind < EnvNAVXYTHETALATCfg.EnvWidth_c; xind++) {
for (yind = 0; yind < EnvNAVXYTHETALATCfg.EnvHeight_c; yind++) {
AddLevelGrid2D[levind][xind][yind] = mapdata[xind + yind * EnvNAVXYTHETALATCfg.EnvWidth_c];
}
}
return true;
}
//set 2D map for the additional level levind
//the version of Set2DMapforAddLev that takes newmap as 2D array instead of one linear array
bool EnvironmentNAVXYTHETAMLEVLAT::Set2DMapforAddLev(const unsigned char** NewGrid2D, int levind)
{
int xind = -1, yind = -1;
if (AddLevelGrid2D == NULL) {
SBPL_ERROR("ERROR: failed to set2Dmap because the map was not allocated previously\n");
return false;
}
for (xind = 0; xind < EnvNAVXYTHETALATCfg.EnvWidth_c; xind++) {
for (yind = 0; yind < EnvNAVXYTHETALATCfg.EnvHeight_c; yind++) {
AddLevelGrid2D[levind][xind][yind] = NewGrid2D[xind][yind];
}
}
return true;
}
/*
update the traversability of a cell<x,y> in addtional level zlev (this is not to update basic level)
*/
bool EnvironmentNAVXYTHETAMLEVLAT::UpdateCostinAddLev(int x, int y, unsigned char newcost, int zlev)
{
#if DEBUG
//SBPL_FPRINTF(fDeb, "Cost updated for cell %d %d at level %d from old cost=%d to new cost=%d\n", x, y, zlev, AddLevelGrid2D[zlev][x][y], newcost);
#endif
AddLevelGrid2D[zlev][x][y] = newcost;
//no need to update heuristics because at this point it is computed solely based on the basic level
return true;
}
//------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2015, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sbpl/heuristics/embedded_heuristic.h>
EmbeddedHeuristic::EmbeddedHeuristic(DiscreteSpaceInformation* environment) :
Heuristic(environment)
{
}
int EmbeddedHeuristic::GetGoalHeuristic(int state_id)
{
return m_environment->GetGoalHeuristic(state_id);
}
int EmbeddedHeuristic::GetStartHeuristic(int state_id)
{
return m_environment->GetStartHeuristic(state_id);
}
int EmbeddedHeuristic::GetFromToHeuristic(int from_id, int to_id)
{
return m_environment->GetFromToHeuristic(from_id, to_id);
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdio>
#ifdef ROS
#include <ros/ros.h>
#endif
#ifndef __CONFIG_H_
#define __CONFIG_H_
/**
* \brief if set, then heuristic is used if available
*/
#define USE_HEUR 1
/**
* \brief memory debugging (available for vc++)
*/
#ifdef WIN32
#define MEM_CHECK 0
#endif
/**
* \brief regular debugging
*/
#define DEBUG 0
/**
* \brief timing debugging
*/
#define TIME_DEBUG 0
/**
* \brief small epsilon for various floating error checking
*/
#define ERR_EPS 0.0000001
#define SBPL_LEVEL_NONE 0
#define SBPL_LEVEL_DEBUG 1
#define SBPL_LEVEL_INFO 2
#define SBPL_LEVEL_WARN 3
#define SBPL_LEVEL_ERROR 4
#define SBPL_LEVEL_FATAL 5
typedef int (*SBPL_PRINT_TEXT_FP)(int level, const char*);
typedef int (*SBPL_FFLUSH_TEXT_FP)(FILE*);
void SET_SBPL_PRINT_TEXT_FP(SBPL_PRINT_TEXT_FP fptr);
void SET_SBPL_FFLUSH_TEXT_FP(SBPL_FFLUSH_TEXT_FP fptr);
int SBPL_PRINTALL(int level, const char* format, ...);
int SBPL_FPRINTALL(FILE* file, const char* format, ...);
int SBPL_FFLUSHALL(FILE* file);
// Standard Output Logger Macros
#ifdef ROS
#define SBPL_DEBUG ROS_DEBUG
#define SBPL_DEBUG_NAMED(a,...) ROS_DEBUG_NAMED("SBPL_" #a,__VA_ARGS__)
#define SBPL_INFO ROS_INFO
#define SBPL_WARN ROS_WARN
#define SBPL_ERROR ROS_ERROR
#define SBPL_FATAL ROS_FATAL
#else
#if DEBUG
#define SBPL_DEBUG(...) SBPL_PRINTALL(SBPL_LEVEL_DEBUG, __VA_ARGS__)
#define SBPL_DEBUG_NAMED(file, ...) SBPL_FPRINTALL(file, __VA_ARGS__)
#define SBPL_INFO(...) SBPL_PRINTALL(SBPL_LEVEL_INFO, __VA_ARGS__)
#define SBPL_WARN(...) SBPL_PRINTALL(SBPL_LEVEL_WARN, __VA_ARGS__)
#define SBPL_ERROR(...) SBPL_PRINTALL(SBPL_LEVEL_ERROR, __VA_ARGS__)
#define SBPL_FATAL(...) SBPL_PRINTALL(SBPL_LEVEL_FATAL, __VA_ARGS__)
#else
#define SBPL_DEBUG(...)
#define SBPL_DEBUG_NAMED(file, ...)
#define SBPL_INFO(...)
#define SBPL_WARN(...)
#define SBPL_ERROR(...)
#define SBPL_FATAL(...)
#endif
#endif
// File Output Logger Macros
#ifdef ROS
#define SBPL_DEBUG_NAMED(a,...) ROS_DEBUG_NAMED("SBPL_" #a,__VA_ARGS__)
#define SBPL_FOPEN(...) (FILE*)1
#define SBPL_FCLOSE(...)
#define SBPL_PRINTF ROS_DEBUG
#define SBPL_FPRINTF(a,...) ROS_DEBUG_NAMED("SBPL_" #a,__VA_ARGS__)
#define SBPL_FFLUSH(...)
#else
#if DEBUG
#define SBPL_FOPEN fopen
#define SBPL_FCLOSE fclose
#define SBPL_PRINTF(...) SBPL_PRINTALL(SBPL_LEVEL_NONE, __VA_ARGS__)
#define SBPL_FPRINTF(file, ...) SBPL_FPRINTALL(file, __VA_ARGS__)
#define SBPL_FFLUSH(file) SBPL_FFLUSHALL(file)
#else
#define SBPL_FOPEN(file, ...) (FILE*)1
#define SBPL_FCLOSE(...)
#define SBPL_PRINTF(...)
#define SBPL_FPRINTF(file, ...)
#define SBPL_FFLUSH(file)
#endif
#endif
#endif

View File

@@ -0,0 +1,297 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ENVIRONMENT_H_
#define __ENVIRONMENT_H_
#include <cstdio>
#include <vector>
#include <sbpl/config.h>
#include <sbpl/sbpl_exception.h>
class CMDPSTATE;
struct MDPConfig;
/**
* \brief base class for environments defining planning graphs
*
* It is independent of the graph search used
* The main means of communication between environment and graph search is
* through stateID. Each state is uniquely defined by stateID and graph
* search is ONLY aware of stateIDs. It doesn't know anything about
* the actual state variables. Environment, on the * other hand, maintains a
* mapping from stateID to actual state variables (coordinates) using
* StateID2IndexMapping array
*/
class DiscreteSpaceInformation
{
public:
/**
* \brief mapping from hashentry stateID (used in environment to contain
* the coordinates of a state, say x,y or x,y,theta)
* to an array of state indices used in searches.
*
* If a single search is done, then it is a single entry. So
* StateID2IndexMapping[100][0] = 5 means that hashentry with stateID 100
* is mapped onto search index = 5 in search 0 The value of -1 means that
* no search state has been created yet for this hashentry
*/
std::vector<int*> StateID2IndexMapping;
/**
* \brief debugging file
*/
FILE* fDeb;
/**
* \brief initialization environment from file (see .cfg files for examples)
*/
virtual bool InitializeEnv(const char* sEnvFile) = 0;
/**
* \brief initialization of MDP data structure
*/
virtual bool InitializeMDPCfg(MDPConfig *MDPCfg) = 0;
/**
* \brief heuristic estimate from state FromStateID to state ToStateID
*/
virtual int GetFromToHeuristic(int FromStateID, int ToStateID) = 0;
/**
* \brief heuristic estimate from state with stateID to goal state
*/
virtual int GetGoalHeuristic(int stateID) = 0;
/**
* \brief heuristic estimate from start state to state with stateID
*/
virtual int GetStartHeuristic(int stateID) = 0;
/** \brief depending on the search used, it may call GetSuccs function
* (for forward search) or GetPreds function (for backward search)
* or both (for incremental search). At least one of this functions should
* be implemented (otherwise, there will be no search to run) Some searches
* may also use SetAllActionsandAllOutcomes or SetAllPreds functions if they
* keep the pointers to successors (predecessors) but most searches do not
* require this, so it is not necessary to support this
*/
virtual void GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV) = 0;
/**
* \brief This version is used with lazy planners. The environment must tell which successors have
* been evaluated fully (and therefore their true cost is being returned) or if it has not been.
* If a successor's cost is not true, then the cost must not overestimate the true cost.
*/
virtual void GetLazySuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost){
throw SBPL_Exception("ERROR: GetLazySuccs is not implemented for this environment");
};
/**
* \brief This version of GetSuccs is needed for E-Graphs. It always returns a unique ID for
* every successor. Generally, this function operates the same as the usual GetSuccs
* and only has different behavior when dealing with an underspecified goal condition
* so that several different states will have to map to the same id number (most planners
* in sbpl use a single goal id number to identify the goal). This function is used
* in conjunction with isGoal.
*/
virtual void GetSuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV){
throw SBPL_Exception("ERROR: GetSuccsWithUniqueIds is not implemented for this environment");
};
/**
* \brief The lazy version of GetSuccsUniqueIds.
*/
virtual void GetLazySuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost){
throw SBPL_Exception("ERROR: GetLazySuccsWithUniqueIds (lazy) is not implemented for this environment");
};
/**
* \brief Used with lazy planners. This evaluates a edge fully that had previously been provided by GetSuccs
* without a "true cost". If the edge is found to be invalid, it should return -1
*/
virtual int GetTrueCost(int parentID, int childID){
throw SBPL_Exception("ERROR: GetTrueCost (used for lazy planning) is not implemented for this environment");
return -1;
};
/**
* \brief This function is generally used with E-Graphs (in conjunction with GetSuccsWithUniqueIds).
*/
virtual bool isGoal(int id){
throw SBPL_Exception("ERROR: isGoal is not implemented for this environment");
return false;
};
/**
* \brief see comments for GetSuccs functon
*/
virtual void GetPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV) = 0;
/**
* \brief see comments for GetSuccs functon
*/
virtual void GetLazyPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost){
throw SBPL_Exception("ERROR: GetLazyPreds is not implemented for this environment");
};
/**
* \brief see comments for GetSuccs functon
*/
virtual void GetPredsWithUniqueIds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV){
SBPL_ERROR("ERROR: GetPredsWithUniqueIds is not implemented for this environment!\n");
throw SBPL_Exception("ERROR: GetPredsWithUniqueIds is not implemented for this environment");
};
/**
* \brief see comments for GetSuccs functon
*/
virtual void GetLazyPredsWithUniqueIds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost){
SBPL_ERROR("ERROR: GetLazyPredsWithUniqueIds is not implemented for this environment!\n");
throw SBPL_Exception("ERROR: GetLazyPredsWithUniqueIds is not implemented for this environment");
};
/**
* \brief see comments for GetSuccs functon
*/
virtual void SetAllActionsandAllOutcomes(CMDPSTATE* state) = 0;
/**
* \brief see comments for GetSuccs functon
*/
virtual void SetAllPreds(CMDPSTATE* state) = 0;
/**
* \brief returns the number of states (hashentries) created
*/
virtual int SizeofCreatedEnv() = 0;
/**
* \brief prints the state variables for a state with stateID
*/
virtual void PrintState(int stateID, bool bVerbose, FILE* fOut = NULL) = 0;
/**
* \brief prints environment config file
*/
virtual void PrintEnv_Config(FILE* fOut) = 0;
/**
* \brief sets a parameter to a value. The set of supported parameters depends on the particular environment
*/
virtual bool SetEnvParameter(const char* parameter, int value)
{
SBPL_ERROR("ERROR: Environment has no parameters that can be set via SetEnvParameter function\n");
return false;
}
/** NOTE - for debugging door planner - ben 8.31.09 */
virtual std::vector<int> GetExpandedStates()
{
SBPL_ERROR("Error: Not yet defined for any environment other than door environment.\n");
std::vector<int> list;
return list;
}
/** \brief returns true if two states meet the same condition, brief this
* is used in some planners to figure out if two states are the same in
* some lower-dimensional manifold for example, in robotarm planning, two
* states could be equivalent if their end effectors are at the same
* position unless overwritten in a child class, this function is not
* implemented
*/
virtual bool AreEquivalent(int StateID1, int StateID2)
{
throw SBPL_Exception("ERROR: environment does not support calls to AreEquivalent function");
}
/** \brief the following two functions generate succs/preds at some
* domain-dependent distance. The number of generated succs/preds is up
* to the environment. NOTE: they MUST generate goal state as a succ/pred if
* it is within the distance from the state CLowV is the corresponding
* vector of lower bounds on the costs from the state to the successor
* states (or vice versa for preds function) unless overwritten in a child
* class, this function is not implemented
*/
virtual void GetRandomSuccsatDistance(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CLowV)
{
throw SBPL_Exception("ERROR: environment does not support calls to GetRandomSuccsatDistance function");
}
/**
* \brief see comments for GetRandomSuccsatDistance
*/
virtual void GetRandomPredsatDistance(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CLowV)
{
throw SBPL_Exception("ERROR: environment does not support calls to GetRandomPredsatDistance function");
}
/**
* \brief checks the heuristics for consistency (some environments do not support this debugging call)
*/
virtual void EnsureHeuristicsUpdated(bool bGoalHeuristics)
{
// by default the heuristics are up-to-date, but in some cases, the
// heuristics are computed only when really needed. For example,
// xytheta environment uses 2D gridsearch as heuristics, and then
// re-computes them only when this function is called. This minimizes
// the number of times heuristics are re-computed which is an expensive
// operation if bGoalHeuristics == true, then it updates goal
// heuristics (for forward search), otherwise it updates start
// heuristics (for backward search)
}
/**
* \brief destructor
*/
virtual ~DiscreteSpaceInformation()
{
SBPL_PRINTF("destroying discretespaceinformation\n");
for (unsigned int i = 0; i < StateID2IndexMapping.size(); ++i) {
if (StateID2IndexMapping[i] != NULL) delete[] StateID2IndexMapping[i];
}
SBPL_FCLOSE(fDeb);
}
/**
* \brief constructor
*/
DiscreteSpaceInformation()
{
#if !defined(ROS) && DEBUG
const char* envdebug = "envdebug.txt";
#endif
if ((fDeb = SBPL_FOPEN(envdebug, "w")) == NULL) {
throw SBPL_Exception("ERROR: failed to open debug file for environment");
}
}
};
#endif

View File

@@ -0,0 +1,178 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ENVIRONMENT_XXX_H_
#define __ENVIRONMENT_XXX_H_
#include <cstdio>
#include <vector>
#include <sbpl/discrete_space_information/environment.h>
#define XXX_MAXACTIONSWIDTH 9
class CMDPACTION;
class CMDPSTATE;
class MDPConfig;
typedef struct ENV_XXX_CONFIG
{
//parameters that are read from the configuration file
unsigned int StartX1;
unsigned int StartX2;
unsigned int StartX3;
unsigned int StartX4;
unsigned int GoalX1;
unsigned int GoalX2;
unsigned int GoalX3;
unsigned int GoalX4;
//derived and initialized elsewhere parameters
} EnvXXXConfig_t;
typedef struct ENVXXXHASHENTRY
{
int stateID;
unsigned int X1;
unsigned int X2;
unsigned int X3;
unsigned int X4;
} EnvXXXHashEntry_t;
typedef struct
{
int startstateid;
int goalstateid;
//hash table of size x_size*y_size. Maps from coords to stateId
int HashTableSize;
std::vector<EnvXXXHashEntry_t*>* Coord2StateIDHashTable;
//vector that maps from stateID to coords
std::vector<EnvXXXHashEntry_t*> StateID2CoordTable;
//any additional variables
} EnvironmentXXX_t;
/** \brief this is just an example of environment and can be used (copy and
* paste) for creating a more complex environment
*/
class EnvironmentXXX : public DiscreteSpaceInformation
{
public:
/**
* \brief see comments on the same function in the parent class
*/
virtual bool InitializeEnv(const char* sEnvFile);
/**
* \brief see comments on the same function in the parent class
*/
virtual bool InitializeMDPCfg(MDPConfig *MDPCfg);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetFromToHeuristic(int FromStateID, int ToStateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetGoalHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetStartHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual void SetAllActionsandAllOutcomes(CMDPSTATE* state);
/**
* \brief see comments on the same function in the parent class
*/
virtual void SetAllPreds(CMDPSTATE* state);
/**
* \brief see comments on the same function in the parent class
*/
virtual void GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV);
/**
* \brief see comments on the same function in the parent class
*/
virtual void GetPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV);
/**
* \brief see comments on the same function in the parent class
*/
virtual int SizeofCreatedEnv();
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintState(int stateID, bool bVerbose, FILE* fOut = NULL);
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintEnv_Config(FILE* fOut);
~EnvironmentXXX() { }
protected:
//member variables
EnvXXXConfig_t EnvXXXCfg;
EnvironmentXXX_t EnvXXX;
virtual void ReadConfiguration(FILE* fCfg);
virtual void InitializeEnvConfig();
virtual unsigned int GETHASHBIN(unsigned int X1, unsigned int X2, unsigned int X3, unsigned int X4);
virtual void PrintHashTableHist();
virtual EnvXXXHashEntry_t* GetHashEntry(unsigned int X1, unsigned int X2, unsigned int X3, unsigned int X4);
virtual EnvXXXHashEntry_t* CreateNewHashEntry(unsigned int X1, unsigned int X2, unsigned int X3, unsigned int X4);
virtual void CreateStartandGoalStates();
virtual void InitializeEnvironment();
virtual void AddAllOutcomes(unsigned int SourceX1, unsigned int SourceX2, unsigned int SourceX3,
unsigned int SourceX4, CMDPACTION* action, int cost);
virtual void ComputeHeuristicValues();
};
#endif

View File

@@ -0,0 +1,391 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ENVIRONMENT_NAV2D_H_
#define __ENVIRONMENT_NAV2D_H_
#include <cstdio>
#include <vector>
#include <sbpl/discrete_space_information/environment.h>
#include <sbpl/utils/utils.h>
#define ENVNAV2D_COSTMULT 1000
#define ENVNAV2D_DEFAULTOBSTHRESH 1 //253-for willow garage //see explanation of the value below
#define ENVNAV2D_MAXDIRS 16 //TODO-debugmax - crashes for 8 in debug mode
class CMDPSTATE;
class MDPConfig;
//configuration parameters
typedef struct ENV_NAV2D_CONFIG
{
ENV_NAV2D_CONFIG()
{
Grid2D = NULL;
}
int EnvWidth_c;
int EnvHeight_c;
int StartX_c;
int StartY_c;
int EndX_c;
int EndY_c;
unsigned char** Grid2D;
//the value at which and above which cells are obstacles in the maps sent from outside
//the default is defined above
unsigned char obsthresh;
int dx_[ENVNAV2D_MAXDIRS];
int dy_[ENVNAV2D_MAXDIRS];
//the intermediate cells through which the actions go
int dxintersects_[ENVNAV2D_MAXDIRS][2];
int dyintersects_[ENVNAV2D_MAXDIRS][2];
//distances of transitions
int dxy_distance_mm_[ENVNAV2D_MAXDIRS];
int numofdirs; //for now either 8 or 16 (default is 8)
} EnvNAV2DConfig_t;
typedef struct ENVHASHENTRY
{
int stateID;
int X;
int Y;
} EnvNAV2DHashEntry_t;
//variables that dynamically change (e.g., array of states, ...)
typedef struct ENVNAV2D
{
ENVNAV2D()
{
Coord2StateIDHashTable = NULL;
}
int startstateid;
int goalstateid;
bool bInitialized;
//hash table of size x_size*y_size. Maps from coords to stateId
int HashTableSize;
std::vector<EnvNAV2DHashEntry_t*>* Coord2StateIDHashTable;
//vector that maps from stateID to coords
std::vector<EnvNAV2DHashEntry_t*> StateID2CoordTable;
//any additional variables
} EnvironmentNAV2D_t;
/**
* \brief 2D (x,y) grid planning problem. For general structure see comments
* on parent class DiscreteSpaceInformation
*/
class EnvironmentNAV2D : public DiscreteSpaceInformation
{
public:
/**
* \brief see comments on the same function in the parent class
*/
virtual bool InitializeEnv(const char* sEnvFile);
/**
*\brief see comments on the same function in the parent class
*/
virtual bool InitializeMDPCfg(MDPConfig *MDPCfg);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetFromToHeuristic(int FromStateID, int ToStateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetGoalHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetStartHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual void SetAllActionsandAllOutcomes(CMDPSTATE* state);
/**
* \brief see comments on the same function in the parent class
*/
virtual void SetAllPreds(CMDPSTATE* state);
/**
* \brief see comments on the same function in the parent class
*/
virtual void GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV);
virtual void GetLazySuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost){
GetSuccs(SourceStateID, SuccIDV, CostV);
isTrueCost->resize(SuccIDV->size(),true);
};
virtual void GetSuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV){
GetSuccs(SourceStateID, SuccIDV, CostV);
};
virtual void GetLazySuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost){
GetLazySuccs(SourceStateID, SuccIDV, CostV, isTrueCost);
};
virtual int GetTrueCost(int parentID, int childID){return -1;};//FIXME: this shouldn't ever be called because we always return true cost...
virtual bool isGoal(int id){
return EnvNAV2D.goalstateid == id;
};
virtual void GetLazyPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost){
GetPreds(TargetStateID, PredIDV, CostV);
isTrueCost->resize(PredIDV->size(),true);
};
virtual void GetPredsWithUniqueIds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV){
GetPreds(TargetStateID, PredIDV, CostV);
};
virtual void GetLazyPredsWithUniqueIds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost){
GetLazyPreds(TargetStateID, PredIDV, CostV, isTrueCost);
};
/**
* \brief see comments on the same function in the parent class
*/
virtual void GetPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV);
/**
* \brief see comments on the same function in the parent class
*/
virtual int SizeofCreatedEnv();
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintState(int stateID, bool bVerbose, FILE* fOut = NULL);
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintEnv_Config(FILE* fOut);
/**
* \brief initialize environment. Gridworld is defined as matrix A of
* size width by height.
* So, internally, it is accessed as A[x][y] with x ranging from 0 to
* width-1 and and y from 0 to height-1. Each element in A[x][y] is unsigned
* char. A[x][y] = 0 corresponds to fully traversable and cost is just
* Euclidean distance. The cost of transition between two neighboring cells
* is EuclideanDistance*(max(A[sourcex][sourcey],A[targetx][targety])+1). If
* A[x][y] >= obsthresh, then in the above equation it is assumed to be
* infinite. mapdata is a pointer to the values of A. If it is null, then A
* is initialized to all zeros. Mapping is: A[x][y] = mapdata[x+y*width]
* start/goal are given by startx, starty, goalx,goaly. If they are not
* known yet, just set them to 0. Later setgoal/setstart can be executed
* finally obsthresh defined obstacle threshold, as mentioned above
*/
virtual bool InitializeEnv(int width, int height,
/** if mapdata is NULL the grid is initialized to all freespace */
const unsigned char* mapdata, int startx, int starty, int goalx, int goaly, unsigned char obsthresh);
/**
* \brief a short version of environment initialization. Here start and goal coordinates will be set to 0s
*
* if mapdata is NULL the grid is initialized to all freespace
*/
virtual bool InitializeEnv(int width, int height, const unsigned char* mapdata, unsigned char obsthresh);
/**
* \brief set start location
*/
virtual int SetStart(int x, int y);
/**
* \brief set goal location
*/
virtual int SetGoal(int x, int y);
/**
* \brief currently, this is not used
*/
virtual void SetGoalTolerance(double tol_x, double tol_y, double tol_theta); /**< not used yet */
/**
* \brief update the traversability of a cell<x,y>
*/
virtual bool UpdateCost(int x, int y, unsigned char newcost);
/** \brief this function fill in Predecessor/Successor states of edges
* whose costs changed
* It takes in an array of cells whose traversability changed, and returns
* (in vector preds_of_changededgesIDV) the IDs of all states that have
* outgoing edges that go through the changed cells
*/
virtual void GetPredsofChangedEdges(std::vector<nav2dcell_t> const * changedcellsV,
std::vector<int> *preds_of_changededgesIDV);
/**
* \brief same as GetPredsofChangedEdges, but returns successor states.
* Both functions need to be present for incremental search
*/
virtual void GetSuccsofChangedEdges(std::vector<nav2dcell_t> const * changedcellsV,
std::vector<int> *succs_of_changededgesIDV);
/**
* \brief returns true if two states meet the same condition - see
* environment.h for more info
*/
virtual bool AreEquivalent(int StateID1, int StateID2);
/**
* \brief generates succs at some domain-dependent distance - see
* environment.h for more info used by certain searches such as R*
*/
virtual void GetRandomSuccsatDistance(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CLowV);
/**
* \brief generates preds at some domain-dependent distance - see
* environment.h for more info
* used by certain searches such as R*
*/
virtual void GetRandomPredsatDistance(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CLowV);
/**
* \brief generates nNumofNeighs random neighbors of cell <X,Y> at
* distance nDist_c (measured in cells)
* it will also generate goal if within this distance as an additional
* neighbor
*/
virtual void GetRandomNeighs(int stateID, std::vector<int>* NeighIDV, std::vector<int>* CLowV, int nNumofNeighs,
int nDist_c, bool bSuccs);
/**
* \brief a direct way to set the configuration of environment - see
* InitializeEnv function for details about the parameters
* it is not a full way to initialize environment. To fully initialize, one
* needs to executed InitGeneral in addition.
*
* if mapdata is NULL the grid is initialized to all freespace
*/
virtual void SetConfiguration(int width, int height, const unsigned char* mapdata,
int startx, int starty,
int goalx, int goaly);
/**
* \brief performs initialization of environments. It is usually called
* in from InitializeEnv. But if SetConfiguration is used, then one
* should call InitGeneral by himself
*/
virtual bool InitGeneral();
/**
* \brief returns the actual <x,y> associated with state of stateID
*/
virtual void GetCoordFromState(int stateID, int& x, int& y) const;
/**
* \brief returns a stateID associated with coordinates <x,y>
*/
virtual int GetStateFromCoord(int x, int y);
/**
* \brief returns true if <x,y> is obstacle (used by the value of this
* cell and obsthresh)
*/
virtual bool IsObstacle(int x, int y);
/**
* \brief returns the cost associated with <x,y> cell, i.e., A[x][y]
*/
virtual unsigned char GetMapCost(int x, int y);
/**
* \brief returns the parameters associated with the current environment.
* This is useful for setting up a copy of an environment (i.e., second
* planning problem)
*/
virtual void GetEnvParms(int *size_x, int *size_y, int* startx, int* starty, int* goalx, int* goaly,
unsigned char* obsthresh);
/**
* \brief way to set up various parameters. For a list of parameters, see
* the body of the function - it is pretty straightforward
*/
virtual bool SetEnvParameter(const char* parameter, int value);
/**
* \brief access to internal configuration data structure
*/
virtual const EnvNAV2DConfig_t* GetEnvNavConfig();
EnvironmentNAV2D();
~EnvironmentNAV2D();
/**
* \brief print some time statistics
*/
virtual void PrintTimeStat(FILE* fOut);
/**
* \brief checks X,Y against map boundaries
*/
virtual bool IsWithinMapCell(int X, int Y);
protected:
//member data
EnvNAV2DConfig_t EnvNAV2DCfg;
EnvironmentNAV2D_t EnvNAV2D;
virtual void ReadConfiguration(FILE* fCfg);
virtual void InitializeEnvConfig();
virtual unsigned int GETHASHBIN(unsigned int X, unsigned int Y);
virtual void PrintHashTableHist();
virtual EnvNAV2DHashEntry_t* GetHashEntry(int X, int Y);
virtual EnvNAV2DHashEntry_t* CreateNewHashEntry(int X, int Y);
virtual void InitializeEnvironment();
virtual void ComputeHeuristicValues();
virtual bool IsValidCell(int X, int Y);
virtual void Computedxy();
};
#endif

View File

@@ -0,0 +1,252 @@
/*
* Copyright (c) 2009, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ENVIRONMENT_NAV2DUU_H_
#define __ENVIRONMENT_NAV2DUU_H_
#include <vector>
#include <cstdio>
#include <sbpl/config.h>
#include <sbpl/discrete_space_information/environment.h>
#include <sbpl/discrete_space_information/environment_nav2D.h>
#include <sbpl/sbpl_exception.h>
#include <sbpl/utils/utils.h>
#define ENVNAV2DUU_COSTMULT 1000
#define NAV2DUU_MAXACTIONSWIDTH 9
#define ENVNAV2DUU_MAXDIRS 8
class CMDPACTION;
class CMDPSTATE;
class MDPConfig;
typedef struct ENV_NAV2DUU_CONFIG
{
//parameters that are read from the configuration file
int EnvWidth_c;
int EnvHeight_c;
int StartX_c;
int StartY_c;
int EndX_c;
int EndY_c;
//cost matrix
unsigned char** Grid2D;
//the value at which and above which cells are obstacles in the maps sent from outside
//the default is defined above
unsigned char obsthresh;
//uncertainty matrix (0 defines P(obstacle) = 0, and 1.0 defines P(obstacle) = 1)
float** UncertaintyGrid2D;
//matrix of hidden variable IDs
int** HiddenVariableXY2ID;
//derived and initialized elsewhere parameters
//possible transitions
int dx_[ENVNAV2DUU_MAXDIRS];
int dy_[ENVNAV2DUU_MAXDIRS];
//distances of transitions
int dxy_distance_mm_[ENVNAV2DUU_MAXDIRS];
//the intermediate cells through which the actions go
int dxintersects_[ENVNAV2D_MAXDIRS][2];
int dyintersects_[ENVNAV2D_MAXDIRS][2];
int numofdirs; //for now can only be 8
//size of environment, number of hidden variables
int sizeofS;
int sizeofH;
} EnvNAV2DUUConfig_t;
#define NAVNAV2DUU_MAXWIDTHHEIGH 1024
#define ENVNAV2DUU_STATEIDTOY(stateID) (stateID%NAVNAV2DUU_MAXWIDTHHEIGH)
#define ENVNAV2DUU_STATEIDTOX(stateID) (stateID/NAVNAV2DUU_MAXWIDTHHEIGH)
#define ENVNAV2DUU_XYTOSTATEID(X, Y) (X*NAVNAV2DUU_MAXWIDTHHEIGH + Y)
typedef struct
{
int startstateid;
int goalstateid;
//any additional variables
bool bInitialized;
} EnvironmentNAV2DUU_t;
/**
* \brief this class is NOT fully yet implemented, please do not use it!
*/
class EnvironmentNAV2DUU : public DiscreteSpaceInformation
{
public:
/**
* \brief see comments on the same function in the parent class
*/
virtual bool InitializeEnv(const char* sEnvFile);
/**
* \brief initialize environment. Gridworld is defined as matrix A of
* size width by height.
* So, internally, it is accessed as A[x][y] with x ranging from 0 to
* width-1 and and y from 0 to height-1. Each element in A[x][y] is unsigned
* char. A[x][y] = 0 corresponds to fully traversable and cost is just
* Euclidean distance. The cost of transition between two neighboring cells
* is EuclideanDistance*(max(A[sourcex][sourcey],A[targetx][targety])+1). If
* A[x][y] >= obsthresh, then in the above equation it is assumed to be
* infinite. mapdata is a pointer to the values of A. If it is null, then A
* is initialized to all zeros. Mapping is: A[x][y] = mapdata[x+y*width]
* start/goal are given by startx, starty, goalx,goaly. If they are not
* known yet, just set them to 0. Later setgoal/setstart can be executed
* finally obsthresh defined obstacle threshold, as mentioned above
* uncertaintymapdata is set up in the same way as mapdata in terms of the
* order in terms of the values, uncertaintymapdata specifies probabilities
* of being obstructed
*/
virtual bool InitializeEnv(int width, int height, const unsigned char* mapdata, const float* uncertaintymapdata,
unsigned char obsthresh);
/**
* \brief set start location
*/
virtual int SetStart(int x, int y);
/**
* \brief set goal location
*/
virtual int SetGoal(int x, int y);
/**
* \brief update the traversability of a cell<x,y>
*/
virtual bool UpdateCost(int x, int y, unsigned char newcost);
/**
* \brief see comments on the same function in the parent class
*/
virtual bool InitializeMDPCfg(MDPConfig *MDPCfg);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetFromToHeuristic(int FromStateID, int ToStateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetGoalHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetStartHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintState(int stateID, bool bVerbose, FILE* fOut = NULL);
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintEnv_Config(FILE* fOut);
EnvironmentNAV2DUU();
~EnvironmentNAV2DUU()
{
}
/**
* \brief not fully implemented yet
*/
virtual void GetPreds(int stateID, const std::vector<sbpl_BinaryHiddenVar_t>* updatedhvaluesV,
std::vector<CMDPACTION>* IncomingDetActionV, std::vector<CMDPACTION>* IncomingStochActionV,
std::vector<sbpl_BinaryHiddenVar_t>* StochActionNonpreferredOutcomeV);
/**
* \brief not fully implemented yet
*/
virtual void SetAllActionsandAllOutcomes(CMDPSTATE* state)
{
throw SBPL_Exception("ERROR: SetAllActionsandAllOutcomes not supported in NAV2D_UNDER_UNCERTAINTY");
}
/**
* \brief not fully implemented yet
*/
virtual void SetAllPreds(CMDPSTATE* state)
{
throw SBPL_Exception("ERROR: SetAllPreds not supported in NAV2D_UNDER_UNCERTAINTY");
}
/**
* \brief not fully implemented yet
*/
virtual void GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV)
{
throw SBPL_Exception("ERROR: GetSuccs not supported in NAV2D_UNDER_UNCERTAINTY");
}
/**
* \brief not fully implemented yet
*/
virtual void GetPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV)
{
throw SBPL_Exception("ERROR: GetPreds not supported in NAV2D_UNDER_UNCERTAINTY");
}
/**
* \brief not fully implemented yet
*/
virtual int SizeofCreatedEnv();
/**
* \brief not fully implemented yet
*/
virtual int SizeofH();
protected:
//member variables
EnvNAV2DUUConfig_t EnvNAV2DUUCfg;
EnvironmentNAV2DUU_t EnvNAV2DUU;
//mapdata and uncertaintymapdata is assumed to be organized into a linear array with y being major: map[x+y*width]
virtual void SetConfiguration(int width, int height, const unsigned char* mapdata, const float* uncertaintymapdata);
virtual void ReadConfiguration(FILE* fCfg);
virtual void InitializeEnvConfig();
virtual void InitializeEnvironment();
virtual void ComputeHeuristicValues();
virtual bool InitGeneral();
virtual bool IsValidRobotPosition(int X, int Y);
virtual bool IsWithinMapCell(int X, int Y);
virtual void Computedxy();
};
#endif

View File

@@ -0,0 +1,688 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ENVIRONMENT_NAVXYTHETALAT_H_
#define __ENVIRONMENT_NAVXYTHETALAT_H_
#include <cstdio>
#include <vector>
#include <sstream>
#include <sbpl/discrete_space_information/environment.h>
#include <sbpl/utils/utils.h>
// Define to test against in client code. Signals that Set2DBlockSize and
// Set2DBucketSize are available in EnvironmentNAVXYTHETALATTICE
#define SBPL_CUSTOM_2D_OPTIONS 1
//eight-connected grid
#define NAVXYTHETALAT_DXYWIDTH 8
#define ENVNAVXYTHETALAT_DEFAULTOBSTHRESH 254 //see explanation of the value below
//maximum number of states for storing them into lookup (as opposed to hash)
#define SBPL_XYTHETALAT_MAXSTATESFORLOOKUP 100000000
//definition of theta orientations
//0 - is aligned with X-axis in the positive direction (1,0 in polar coordinates)
//theta increases as we go counterclockwise
//number of theta values - should be power of 2
#define NAVXYTHETALAT_THETADIRS 16
//number of actions per x,y,theta state
//decrease, increase, same angle while moving plus decrease, increase angle while standing.
#define NAVXYTHETALAT_DEFAULT_ACTIONWIDTH 5
#define NAVXYTHETALAT_COSTMULT_MTOMM 1000
class CMDPSTATE;
class MDPConfig;
class SBPL2DGridSearch;
struct EnvNAVXYTHETALATAction_t
{
unsigned char aind; //index of the action (unique for given starttheta)
char starttheta;
char dX;
char dY;
char endtheta;
unsigned int cost;
std::vector<sbpl_2Dcell_t> intersectingcellsV;
//start at 0,0,starttheta and end at endcell in continuous domain with half-bin less to account for 0,0 start
std::vector<sbpl_xy_theta_pt_t> intermptV;
//start at 0,0,starttheta and end at endcell in discrete domain
std::vector<sbpl_xy_theta_cell_t> interm3DcellsV;
int motprimID;
double turning_radius;
};
struct EnvNAVXYTHETALATHashEntry_t
{
int stateID;
int X;
int Y;
char Theta;
int iteration;
};
struct SBPL_xytheta_mprimitive
{
int motprimID;
unsigned char starttheta_c;
int additionalactioncostmult;
sbpl_xy_theta_cell_t endcell;
double turning_radius;
//intermptV start at 0,0,starttheta and end at endcell in continuous
//domain with half-bin less to account for 0,0 start
std::vector<sbpl_xy_theta_pt_t> intermptV;
};
//variables that dynamically change (e.g., array of states, ...)
struct EnvironmentNAVXYTHETALAT_t
{
int startstateid;
int goalstateid;
bool bInitialized;
//any additional variables
};
//configuration parameters
struct EnvNAVXYTHETALATConfig_t
{
int EnvWidth_c;
int EnvHeight_c;
int NumThetaDirs;
int StartX_c;
int StartY_c;
int StartTheta;
int EndX_c;
int EndY_c;
int EndTheta;
unsigned char** Grid2D;
std::vector<double> ThetaDirs;
double StartTheta_rad;
double EndTheta_rad;
double min_turning_radius_m;
// the value at which and above which cells are obstacles in the maps sent from outside
// the default is defined above
unsigned char obsthresh;
// the value at which and above which until obsthresh (not including it)
// cells have the nearest obstacle at distance smaller than or equal to
// the inner circle of the robot. In other words, the robot is definitely
// colliding with the obstacle, independently of its orientation
// if no such cost is known, then it should be set to obsthresh (if center
// of the robot collides with obstacle, then the whole robot collides with
// it independently of its rotation)
unsigned char cost_inscribed_thresh;
// the value at which and above which until cost_inscribed_thresh (not including it) cells
// **may** have a nearest osbtacle within the distance that is in between
// the robot inner circle and the robot outer circle
// any cost below this value means that the robot will NOT collide with any
// obstacle, independently of its orientation
// if no such cost is known, then it should be set to 0 or -1 (then no cell
// cost will be lower than it, and therefore the robot's footprint will
// always be checked)
int cost_possibly_circumscribed_thresh; // it has to be integer, because -1 means that it is not provided.
double nominalvel_mpersecs;
//double nominalangvel_radpersecs;
double timetoturn45degsinplace_secs;
double cellsize_m;
int dXY[NAVXYTHETALAT_DXYWIDTH][2];
//array of actions, ActionsV[i][j] - jth action for sourcetheta = i
EnvNAVXYTHETALATAction_t** ActionsV;
//PredActionsV[i] - vector of pointers to the actions that result in a state with theta = i
std::vector<EnvNAVXYTHETALATAction_t*>* PredActionsV;
int actionwidth; //number of motion primitives
std::vector<SBPL_xytheta_mprimitive> mprimV;
std::vector<sbpl_2Dpt_t> FootprintPolygon;
};
class EnvNAVXYTHETALAT_InitParms
{
public:
unsigned int numThetas;
const unsigned char* mapdata;
double startx;
double starty;
double starttheta;
double goalx;
double goaly;
double goaltheta;
double goaltol_x;
double goaltol_y;
double goaltol_theta;
};
/** \brief 3D (x,y,theta) planning using lattice-based graph problem. For
* general structure see comments on parent class DiscreteSpaceInformation
* For info on lattice-based planning used here, you can check out the paper:
* Maxim Likhachev and Dave Ferguson, " Planning Long Dynamically-Feasible
* Maneuvers for Autonomous Vehicles", IJRR'09
*/
class EnvironmentNAVXYTHETALATTICE : public DiscreteSpaceInformation
{
public:
EnvironmentNAVXYTHETALATTICE();
/**
* \brief initialization of environment from file. See .cfg files for
* examples it also takes the perimeter of the robot with respect to some
* reference point centered at x=0,y=0 and orientation = 0 (along x axis).
* The perimeter is defined in meters as a sequence of vertices of a
* polygon defining the perimeter. If vector is of zero size, then robot
* is assumed to be point robot (you may want to inflate all obstacles by
* its actual radius) Motion primitives file defines the motion primitives
* available to the robot
*/
virtual bool InitializeEnv(const char* sEnvFile, const std::vector<sbpl_2Dpt_t>& perimeterptsV,
const char* sMotPrimFile);
// ?? virtual bool InitializeEnv(const ENVNAVXYTHETAVELOLAT_InitParms & params);
/**
* \brief see comments on the same function in the parent class
*/
virtual bool InitializeEnv(const char* sEnvFile);
/**
* \brief way to set up various parameters. For a list of parameters, see
* the body of the function - it is pretty straightforward
*/
virtual bool SetEnvParameter(const char* parameter, int value);
/**
* \brief returns the value of specific parameter - see function body for the list of parameters
*/
virtual int GetEnvParameter(const char* parameter);
/**
* \brief see comments on the same function in the parent class
*/
virtual bool InitializeMDPCfg(MDPConfig *MDPCfg);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetFromToHeuristic(int FromStateID, int ToStateID) = 0;
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetGoalHeuristic(int stateID) = 0;
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetStartHeuristic(int stateID) = 0;
/**
* \brief see comments on the same function in the parent class
*/
virtual void SetAllActionsandAllOutcomes(CMDPSTATE* state) = 0;
/**
* \brief see comments on the same function in the parent class
*/
virtual void SetAllPreds(CMDPSTATE* state);
/**
* \brief see comments on the same function in the parent class
*/
virtual void GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV);
virtual void GetLazySuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost);
virtual void GetSuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV);
virtual void GetLazySuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost);
/**
* \brief see comments on the same function in the parent class
*/
virtual void GetPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV) = 0;
/**
* \brief see comments on the same function in the parent class
*/
virtual void EnsureHeuristicsUpdated(bool bGoalHeuristics);
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintEnv_Config(FILE* fOut);
/**
* \brief set the block size for the 2D heuristic. A block size of 1 is the default and will result in
* a single cell in the 2D heuristic search corresponding to 1 cell from the source map.
* A block size of 2 will result in a single cell in the 2D heuristic search corresponding to
* a 2x2 set of blocks from the source map with a cost of the max of the 2x2 source cells.
*/
virtual void Set2DBlockSize(int BlockSize);
/**
* @brief Set2DBucketSize Set the initial size of the CSlidingBuckets used for the fringe priority list
* @param BucketSize
*/
virtual void Set2DBucketSize(int BucketSize);
virtual double DiscTheta2ContNew(int theta) const;
virtual int ContTheta2DiscNew(double theta) const;
virtual double DiscTheta2ContFromSet(int theta) const;
virtual int ContTheta2DiscFromSet(double theta) const;
virtual int normalizeDiscAngle(int theta) const;
/**
* \brief initialize environment. Gridworld is defined as matrix A of size width by height.
* So, internally, it is accessed as A[x][y] with x ranging from 0 to width-1 and and y from 0 to height-1
* Each element in A[x][y] is unsigned char. A[x][y] = 0 corresponds to
* fully traversable and cost is just Euclidean distance
* The cost of transition between two neighboring cells is
* EuclideanDistance*(max(A[sourcex][sourcey],A[targetx][targety])+1)
* f A[x][y] >= obsthresh, then in the above equation it is assumed to be infinite.
* The cost also incorporates the length of a motion primitive and its cost_multiplier (see getcost function)
* mapdata is a pointer to the values of A. If it is null, then A is
* initialized to all zeros. Mapping is: A[x][y] = mapdata[x+y*width]
* start/goal are given by startx, starty, starttheta, goalx,goaly, goaltheta in meters/radians.
* If they are not known yet, just set them to 0. Later setgoal/setstart can be executed
* finally obsthresh defined obstacle threshold, as mentioned above
* goaltolerances are currently ignored
* for explanation of perimeter, see comments for InitializeEnv function that reads all from file
* cellsize is discretization in meters
* nominalvel_mpersecs is assumed velocity of vehicle while moving forward in m/sec
* timetoturn45degsinplace_secs is rotational velocity in secs/45 degrees turn
*/
virtual bool InitializeEnv(int width, int height,
/** if mapdata is NULL the grid is initialized to all freespace */
const unsigned char* mapdata,
double startx, double starty, double starttheta,
double goalx, double goaly, double goaltheta,
double goaltol_x, double goaltol_y, double goaltol_theta,
const std::vector<sbpl_2Dpt_t>& perimeterptsV, double cellsize_m,
double nominalvel_mpersecs, double timetoturn45degsinplace_secs,
unsigned char obsthresh, const char* sMotPrimFile);
/**
* \brief Same as the above InitializeEnv except that only the parameters
* that area really needed are required. The additional (optional)
* parameters may be given in the params object (including the ability to
* specify the number of thetas)
*/
virtual bool InitializeEnv(int width, int height, const std::vector<sbpl_2Dpt_t> & perimeterptsV, double cellsize_m,
double nominalvel_mpersecs, double timetoturn45degsinplace_secs,
unsigned char obsthresh, const char* sMotPrimFile, EnvNAVXYTHETALAT_InitParms params);
/**
* \brief update the traversability of a cell<x,y>
*/
virtual bool UpdateCost(int x, int y, unsigned char newcost);
/**
* \brief re-setting the whole 2D map
* transform from linear array mapdata to the 2D matrix used internally: Grid2D[x][y] = mapdata[x+y*width]
*/
virtual bool SetMap(const unsigned char* mapdata);
/**
* \brief this function fill in Predecessor/Successor states of edges whose costs changed
* It takes in an array of cells whose traversability changed, and
* returns (in vector preds_of_changededgesIDV) the IDs of all
* states that have outgoing edges that go through the changed
* cells
*/
virtual void GetPredsofChangedEdges(std::vector<nav2dcell_t> const * changedcellsV,
std::vector<int> *preds_of_changededgesIDV) = 0;
/**
* \brief same as GetPredsofChangedEdges, but returns successor states.
* Both functions need to be present for incremental search
*/
virtual void GetSuccsofChangedEdges(std::vector<nav2dcell_t> const * changedcellsV,
std::vector<int> *succs_of_changededgesIDV) = 0;
/**
* returns true if cell is untraversable
*/
virtual bool IsObstacle(int x, int y);
/**
* \brief returns false if robot intersects obstacles or lies outside of
* the map. Note this is pretty expensive operation since it computes the
* footprint of the robot based on its x,y,theta
*/
virtual bool IsValidConfiguration(int X, int Y, int Theta);
/**
* \brief returns environment parameters. Useful for creating a copy environment
*/
virtual void GetEnvParms(int *size_x, int *size_y, double* startx, double* starty, double* starttheta,
double* goalx, double* goaly, double* goaltheta, double* cellsize_m,
double* nominalvel_mpersecs, double* timetoturn45degsinplace_secs,
unsigned char* obsthresh, std::vector<SBPL_xytheta_mprimitive>* motionprimitiveV);
/**
* \brief returns environment parameters. Useful for creating a copy environment
*/
virtual void GetEnvParms(int *size_x, int *size_y, int* num_thetas, double* startx, double* starty,
double* starttheta, double* goalx, double* goaly, double* goaltheta, double* cellsize_m,
double* nominalvel_mpersecs, double* timetoturn45degsinplace_secs,
unsigned char* obsthresh, std::vector<SBPL_xytheta_mprimitive>* motionprimitiveV);
/**
* \brief get internal configuration data structure
*/
virtual const EnvNAVXYTHETALATConfig_t* GetEnvNavConfig();
virtual ~EnvironmentNAVXYTHETALATTICE();
/**
* \brief prints time statistics
*/
virtual void PrintTimeStat(FILE* fOut);
/**
* \brief returns the cost corresponding to the cell <x,y>
*/
virtual unsigned char GetMapCost(int x, int y);
/**
* \brief returns true if cell is within map
*/
virtual bool IsWithinMapCell(int X, int Y);
/**
* \brief Transform a pose into discretized form. The angle 'pth' is
* considered to be valid if it lies between -2pi and 2pi (some
* people will prefer 0<=pth<2pi, others -pi<pth<=pi, so this
* compromise should suit everyone).
*
* \note Even if this method returns false, you can still use the
* computed indices, for example to figure out how big your map
* should have been.
*
* \return true if the resulting indices lie within the grid bounds
* and the angle was valid.
*/
virtual bool PoseContToDisc(double px, double py, double pth, int &ix, int &iy, int &ith) const;
/** \brief Transform grid indices into a continuous pose. The computed
* angle lies within 0<=pth<2pi.
*
* \note Even if this method returns false, you can still use the
* computed indices, for example to figure out poses that lie
* outside of your current map.
*
* \return true if all the indices are within grid bounds.
*/
virtual bool PoseDiscToCont(int ix, int iy, int ith, double &px, double &py, double &pth) const;
/**
* \brief prints environment variables for debugging
*/
virtual void PrintVars() { }
protected:
virtual int GetActionCost(int SourceX, int SourceY, int SourceTheta, EnvNAVXYTHETALATAction_t* action);
//member data
EnvNAVXYTHETALATConfig_t EnvNAVXYTHETALATCfg;
EnvironmentNAVXYTHETALAT_t EnvNAVXYTHETALAT;
std::vector<sbpl_xy_theta_cell_t> affectedsuccstatesV; //arrays of states whose outgoing actions cross cell 0,0
std::vector<sbpl_xy_theta_cell_t> affectedpredstatesV; //arrays of states whose incoming actions cross cell 0,0
int iteration;
int blocksize; // 2D block size
int bucketsize; // 2D bucket size
bool bUseNonUniformAngles;
//2D search for heuristic computations
bool bNeedtoRecomputeStartHeuristics; //set whenever grid2Dsearchfromstart needs to be re-executed
bool bNeedtoRecomputeGoalHeuristics; //set whenever grid2Dsearchfromgoal needs to be re-executed
SBPL2DGridSearch* grid2Dsearchfromstart; //computes h-values that estimate distances from start x,y to all cells
SBPL2DGridSearch* grid2Dsearchfromgoal; //computes h-values that estimate distances to goal x,y from all cells
virtual void ReadConfiguration(FILE* fCfg);
virtual void InitializeEnvConfig(std::vector<SBPL_xytheta_mprimitive>* motionprimitiveV);
virtual bool CheckQuant(FILE* fOut);
virtual void SetConfiguration(int width, int height,
/** if mapdata is NULL the grid is initialized to all freespace */
const unsigned char* mapdata,
int startx, int starty, int starttheta,
int goalx, int goaly, int goaltheta,
double cellsize_m, double nominalvel_mpersecs, double timetoturn45degsinplace_secs,
const std::vector<sbpl_2Dpt_t> & robot_perimeterV);
virtual bool InitGeneral(std::vector<SBPL_xytheta_mprimitive>* motionprimitiveV);
virtual void PrecomputeActionswithBaseMotionPrimitive(std::vector<SBPL_xytheta_mprimitive>* motionprimitiveV);
virtual void PrecomputeActionswithCompleteMotionPrimitive(std::vector<SBPL_xytheta_mprimitive>* motionprimitiveV);
virtual void DeprecatedPrecomputeActions();
virtual void InitializeEnvironment() = 0;
virtual void ComputeHeuristicValues();
virtual bool IsValidCell(int X, int Y);
virtual void CalculateFootprintForPose(sbpl_xy_theta_pt_t pose, std::vector<sbpl_2Dcell_t>* footprint);
virtual void CalculateFootprintForPose(sbpl_xy_theta_pt_t pose, std::vector<sbpl_2Dcell_t>* footprint,
const std::vector<sbpl_2Dpt_t>& FootprintPolygon);
virtual void RemoveSourceFootprint(sbpl_xy_theta_pt_t sourcepose, std::vector<sbpl_2Dcell_t>* footprint);
virtual void RemoveSourceFootprint(sbpl_xy_theta_pt_t sourcepose, std::vector<sbpl_2Dcell_t>* footprint,
const std::vector<sbpl_2Dpt_t>& FootprintPolygon);
virtual void GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV,
std::vector<EnvNAVXYTHETALATAction_t*>* actionindV = NULL) = 0;
virtual void GetLazySuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost, std::vector<EnvNAVXYTHETALATAction_t*>* actionindV = NULL) = 0;
virtual void GetSuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<EnvNAVXYTHETALATAction_t*>* actionindV = NULL) = 0;
virtual void GetLazySuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost, std::vector<EnvNAVXYTHETALATAction_t*>* actionindV = NULL) = 0;
virtual int GetTrueCost(int parentID, int childID) = 0;
virtual bool isGoal(int id) = 0;
virtual double EuclideanDistance_m(int X1, int Y1, int X2, int Y2);
virtual void ComputeReplanningData();
virtual void ComputeReplanningDataforAction(EnvNAVXYTHETALATAction_t* action);
virtual bool ReadMotionPrimitives(FILE* fMotPrims);
virtual bool ReadinMotionPrimitive(SBPL_xytheta_mprimitive* pMotPrim, FILE* fIn);
virtual bool ReadinCell(sbpl_xy_theta_cell_t* cell, FILE* fIn);
virtual bool ReadinPose(sbpl_xy_theta_pt_t* pose, FILE* fIn);
virtual void PrintHeuristicValues();
};
class EnvironmentNAVXYTHETALAT : public EnvironmentNAVXYTHETALATTICE
{
public:
EnvironmentNAVXYTHETALAT()
{
HashTableSize = 0;
Coord2StateIDHashTable = NULL;
Coord2StateIDHashTable_lookup = NULL;
}
~EnvironmentNAVXYTHETALAT();
/**
* \brief sets start in meters/radians
*/
virtual int SetStart(double x, double y, double theta);
/**
* \brief sets goal in meters/radians
*/
virtual int SetGoal(double x, double y, double theta);
/**
* \brief sets goal tolerance. (Note goal tolerance is ignored currently)
*/
virtual void SetGoalTolerance(double tol_x, double tol_y, double tol_theta) { /**< not used yet */ }
/**
* \brief returns state coordinates of state with ID=stateID
*/
virtual void GetCoordFromState(int stateID, int& x, int& y, int& theta) const;
/**
* \brief returns stateID for a state with coords x,y,theta
*/
virtual int GetStateFromCoord(int x, int y, int theta);
/**
* \brief returns the actions / motion primitives of the passed path.
*/
virtual void GetActionsFromStateIDPath(std::vector<int>* stateIDPath,
std::vector<EnvNAVXYTHETALATAction_t>* action_list);
/** \brief converts a path given by stateIDs into a sequence of
* coordinates. Note that since motion primitives are short actions
* represented as a sequence of points,
* the path returned by this function contains much more points than the
* number of points in the input path. The returned coordinates are in
* meters,meters,radians
*/
virtual void ConvertStateIDPathintoXYThetaPath(std::vector<int>* stateIDPath,
std::vector<sbpl_xy_theta_pt_t>* xythetaPath);
/**
* \brief prints state info (coordinates) into file
*/
virtual void PrintState(int stateID, bool bVerbose, FILE* fOut = NULL);
/**
* \brief returns all predecessors states and corresponding costs of actions
*/
virtual void GetPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV);
virtual void GetLazyPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost);
virtual void GetPredsWithUniqueIds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV);
virtual void GetLazyPredsWithUniqueIds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost);
/**
* \brief returns all successors states, costs of corresponding actions
* and pointers to corresponding actions, each of which is a motion
* primitive
* if actionindV is NULL, then pointers to actions are not returned
*/
virtual void GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV,
std::vector<EnvNAVXYTHETALATAction_t*>* actionindV = NULL);
virtual void GetLazySuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost, std::vector<EnvNAVXYTHETALATAction_t*>* actionindV = NULL);
virtual void GetSuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<EnvNAVXYTHETALATAction_t*>* actionindV = NULL);
virtual void GetLazySuccsWithUniqueIds(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV, std::vector<bool>* isTrueCost, std::vector<EnvNAVXYTHETALATAction_t*>* actionindV = NULL);
virtual int GetTrueCost(int parentID, int childID);
virtual bool isGoal(int id);
/** \brief this function fill in Predecessor/Successor states of edges
* whose costs changed
* It takes in an array of cells whose traversability changed, and returns
* (in vector preds_of_changededgesIDV) the IDs of all states that have
* outgoing edges that go through the changed cells
*/
virtual void GetPredsofChangedEdges(std::vector<nav2dcell_t> const * changedcellsV,
std::vector<int> *preds_of_changededgesIDV);
/**
* \brief same as GetPredsofChangedEdges, but returns successor states.
* Both functions need to be present for incremental search
*/
virtual void GetSuccsofChangedEdges(std::vector<nav2dcell_t> const * changedcellsV,
std::vector<int> *succs_of_changededgesIDV);
/**
* \brief see comments on the same function in the parent class
*/
virtual void SetAllActionsandAllOutcomes(CMDPSTATE* state);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetFromToHeuristic(int FromStateID, int ToStateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetGoalHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetStartHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int SizeofCreatedEnv();
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintVars() { }
const EnvNAVXYTHETALATHashEntry_t* GetStateEntry(int state_id) const;
protected:
//hash table of size x_size*y_size. Maps from coords to stateId
int HashTableSize;
std::vector<EnvNAVXYTHETALATHashEntry_t*>* Coord2StateIDHashTable;
//vector that maps from stateID to coords
std::vector<EnvNAVXYTHETALATHashEntry_t*> StateID2CoordTable;
EnvNAVXYTHETALATHashEntry_t** Coord2StateIDHashTable_lookup;
virtual unsigned int GETHASHBIN(unsigned int X, unsigned int Y, unsigned int Theta);
virtual EnvNAVXYTHETALATHashEntry_t* GetHashEntry_hash(int X, int Y, int Theta);
virtual EnvNAVXYTHETALATHashEntry_t* CreateNewHashEntry_hash(int X, int Y, int Theta);
virtual EnvNAVXYTHETALATHashEntry_t* GetHashEntry_lookup(int X, int Y, int Theta);
virtual EnvNAVXYTHETALATHashEntry_t* CreateNewHashEntry_lookup(int X, int Y, int Theta);
//pointers to functions
EnvNAVXYTHETALATHashEntry_t* (EnvironmentNAVXYTHETALAT::*GetHashEntry)(int X, int Y, int Theta);
EnvNAVXYTHETALATHashEntry_t* (EnvironmentNAVXYTHETALAT::*CreateNewHashEntry)(int X, int Y, int Theta);
virtual void InitializeEnvironment();
virtual void PrintHashTableHist(FILE* fOut);
};
#endif

View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ENVIRONMENT_NAVXYTHETAMLEVLAT_H_
#define __ENVIRONMENT_NAVXYTHETAMLEVLAT_H_
#include <vector>
#include <sbpl/discrete_space_information/environment_navxythetalat.h>
#include <sbpl/sbpl_exception.h>
#include <sbpl/utils/utils.h>
// these structures contain footprints for the additional levels
// each of these structures corresponds to one of the EnvNAVXYTHETALATAction_t structures
typedef struct
{
char starttheta; // should be equal to the corresponding EnvNAVXYTHETALATAction_t structure
char dX; // should be equal to the corresponding EnvNAVXYTHETALATAction_t structure
char dY; // should be equal to the corresponding EnvNAVXYTHETALATAction_t structure
char endtheta; // should be equal to the corresponding EnvNAVXYTHETALATAction_t structure
std::vector<sbpl_2Dcell_t>* intersectingcellsV; // one footprint per additional level
} EnvNAVXYTHETAMLEVLATAddInfoAction_t;
/**
* \brief This is x,y,theta lattice planning but with multiple levels in z.
* In other words, it is for doing collision checking in 3D (x,y,z). The z
* level is split into numofzlevs levels. If numofzlevs = 1, then it
* defaults to the original x,y,theta lattice planning defined in
* EnvironmentNAVXYTHETALAT. Otherwise, it uses numofzlevs footprints of the
* robot and corresponding costmaps. It assumes that they correspond to each
* other and are projections of the robot and corresponding z regions of the
* 3D map.
*/
class EnvironmentNAVXYTHETAMLEVLAT : public EnvironmentNAVXYTHETALAT
{
public:
/**
* \brief initialization of additional levels. 0 is the original one. All additional ones will start with index 1
* For each level, it also takes cost thresholds for cells lying
* within inner radius of the robot (inscribed) and outside of the
* inner circle but within outer radius (possibly_circumscribed).
* See environment_navxythetalat.h for the explanation of these
* parameters.
*/
bool InitializeAdditionalLevels(int numofadditionalzlevs, const std::vector<sbpl_2Dpt_t>* perimeterptsV,
unsigned char* cost_inscribed_thresh,
unsigned char* cost_possibly_circumscribed_thresh);
/**
* \brief setting 2D map for the additional level at levind index
* (indices are zero-based and are only used to index the additional levels)
* you can not use this function to set 2D map for the base level
* transform from linear array mapdata to the 2D matrix used internally: Grid2D[x][y] = mapdata[x+y*width]
*/
bool Set2DMapforAddLev(const unsigned char* mapdata, int levind);
/**
* \brief set 2D map for the additional level levind
* The version of Set2DMapforAddLev that takes newmap as 2D array instead of one linear array
*/
bool Set2DMapforAddLev(const unsigned char** NewGrid2D, int levind);
/**
* \brief update the traversability of a cell<x,y> in level zlev
*/
bool UpdateCostinAddLev(int x, int y, unsigned char newcost, int zlev);
/**
* \brief incremental planning not supported
*/
virtual void GetPredsofChangedEdges(std::vector<nav2dcell_t> const * changedcellsV,
std::vector<int> *preds_of_changededgesIDV)
{
throw SBPL_Exception("ERROR: GetPredsofChangedEdges function not supported");
}
/**
* \brief incremental planning not supported
*/
virtual void GetSuccsofChangedEdges(std::vector<nav2dcell_t> const * changedcellsV,
std::vector<int> *succs_of_changededgesIDV)
{
throw SBPL_Exception("ERROR: GetSuccsofChangedEdges function not supported");
}
/**
* returns true if cell is traversable and within map limits - it checks against all levels including the base one
*/
bool IsValidCell(int X, int Y);
/**
* returns true if cell is traversable and within map limits for a particular level
*/
bool IsValidCell(int X, int Y, int levind);
/**
* returns true if cell is untraversable at any level
*/
bool IsObstacle(int x, int y);
/**
* returns true if cell is untraversable at level levelnum.
*/
bool IsObstacle(int x, int y, int levind);
/**
* \brief returns false if robot intersects obstacles or lies outside of the map.
* Note this is pretty expensive operation since it computes the footprint
* of the robot based on its x,y,theta
*/
bool IsValidConfiguration(int X, int Y, int Theta);
/**
* \brief returns the maximum over all levels of the cost corresponding to the cell <x,y>
*/
unsigned char GetMapCost(int X, int Y);
/**
* \brief returns the cost corresponding to the cell <x,y> at level levind
*/
unsigned char GetMapCost(int X, int Y, int levind);
EnvironmentNAVXYTHETAMLEVLAT();
~EnvironmentNAVXYTHETAMLEVLAT();
protected:
/**
* \brief number of additional levels. If it is 0, then there is only one level - base level
*/
int numofadditionalzlevs;
/**
* \brief footprints for the additional levels
*/
std::vector<sbpl_2Dpt_t>* AddLevelFootprintPolygonV;
/**
* \brief array of additional info in actions,
* AdditionalInfoinActionsV[i][j] - jth action for sourcetheta = i
* basically, each Additional info structure will contain numofadditionalzlevs additional intersecting
* cells vector<sbpl_2Dcell_t> intersectingcellsV
*/
EnvNAVXYTHETAMLEVLATAddInfoAction_t** AdditionalInfoinActionsV;
/**
* \brief 2D maps for additional levels.
* AddLevelGrid2D[lind][x][y] refers to <x,y> cell on the additional level lind
*/
unsigned char*** AddLevelGrid2D;
/**
* \brief inscribed cost thresholds for additional levels
* see environment_navxythetalat.h file for the explanation of this threshold
*/
unsigned char* AddLevel_cost_inscribed_thresh;
/**
* \brief possibly_circumscribed cost thresholds for additional levels
* see environment_navxythetalat.h file for the explanation of this threshold
*/
unsigned char* AddLevel_cost_possibly_circumscribed_thresh;
virtual int GetActionCost(int SourceX, int SourceY, int SourceTheta, EnvNAVXYTHETALATAction_t* action);
virtual int GetActionCostacrossAddLevels(int SourceX, int SourceY, int SourceTheta,
EnvNAVXYTHETALATAction_t* action);
};
#endif

View File

@@ -0,0 +1,404 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __PRECOMPUTED_ADJACENCY_LIST_H_
#define __PRECOMPUTED_ADJACENCY_LIST_H_
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <list>
#include <map>
#include <utility>
#include <vector>
#include <sbpl/discrete_space_information/environment.h>
#include <sbpl/sbpl_exception.h>
#include <sbpl/planners/araplanner.h>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/mdp.h>
#include <sbpl/utils/mdpconfig.h>
struct Adjacency
{
int neighbor;
int cost;
};
typedef std::list<Adjacency> Adjacencies;
typedef Adjacencies::iterator AdjListIterator;
/**
* \brief SBPL Environment represented as an adjacency list graph.
*
* \tparam Coords Coords must be a type that 1) has operator<< and
* heuristicDistanceTo (const Coords&) const defined on it 2) can be used as a
* key of an STL map
*
* Nodes of the graph are labelled with Coords. Edges have integer costs
* attached to them. ARA* planning is done on this graph, and the function
* heuristicDistanceTo is used as the admissible heuristic.
*/
template<class Coords>
class AdjacencyListSBPLEnv : public DiscreteSpaceInformation
{
public:
AdjacencyListSBPLEnv();
void writeToStream(std::ostream& str = std::cout);
/**
* \brief Add point to roadmap. Does not check for duplicates.
*/
void addPoint(const Coords& c);
/**
* \brief Does the roadmap contain this point?
*/
bool hasPoint(const Coords& c);
/**
* \brief Remove the last N points added using addPoint (and all their incident edges) in O(N) time
*/
void removeLastPoints(unsigned int n = 1);
/**
* \post An undirected edge exists between c1 and c2 with the given cost
* cost, if not provided, defaults to the heuristic cost between c1 and c2
*/
void setCost(const Coords& c1, const Coords& c2, int cost);
void setCost(const Coords& c1, const Coords& c2);
void setStartState(const Coords& c);
void setGoalState(const Coords& c);
/**
* \brief Use ARA* to find an optimal path between the currently set start and goal states
* \return Vector of states on the path
* \post solution_cost will hold the cost of the returned solution
*/
std::vector<Coords> findOptimalPath(int* solution_cost);
// Inherited DiscreteSpaceInformation ops
bool InitializeEnv(const char* sEnvFile);
bool InitializeMDPCfg(MDPConfig *MDPCfg);
int GetFromToHeuristic(int FromStateID, int ToStateID);
int GetGoalHeuristic(int stateID);
int GetStartHeuristic(int stateID);
void SetAllActionsandAllOutcomes(CMDPSTATE* state);
void SetAllPreds(CMDPSTATE* state);
void GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV);
void GetPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV);
int SizeofCreatedEnv();
void PrintState(int stateID, bool bVerbose, FILE* fOut = NULL);
void PrintEnv_Config(FILE* fOut);
private:
void resetStateId2IndexMapping(void);
// Members
std::vector<Coords> points_;
std::map<Coords, int> pointIds_;
std::vector<Adjacencies> adjacency_vector_;
int startStateId_;
int goalStateId_;
};
template<class Coords>
AdjacencyListSBPLEnv<Coords>::AdjacencyListSBPLEnv() :
startStateId_(-1), goalStateId_(-1)
{
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::writeToStream(std::ostream& str)
{
int numStates = points_.size();
str << "Adjacency list SBPL Env " << endl;
for (unsigned int i = 0; i < points_.size(); i++) {
str << i << ". " << points_[i] << ". Neighbors: ";
for (AdjListIterator iter = adjacency_vector_[i].begin(); iter != adjacency_vector_[i].end(); iter++) {
if (iter->neighbor < numStates) {
str << "[" << points_[iter->neighbor] << " " << iter->cost << "] ";
}
else {
str << "[To-Be-Deleted Edge] ";
}
}
str << endl;
}
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::addPoint(const Coords& c)
{
pointIds_[c] = points_.size();
Adjacencies a;
points_.push_back(c);
adjacency_vector_.push_back(a);
int* entry = new int[NUMOFINDICES_STATEID2IND];
for (unsigned int i = 0; i < NUMOFINDICES_STATEID2IND; i++) {
entry[i] = -1;
}
StateID2IndexMapping.push_back(entry);
}
template<class Coords>
bool AdjacencyListSBPLEnv<Coords>::hasPoint(const Coords& c)
{
return !(pointIds_.find(c) == pointIds_.end());
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::removeLastPoints(unsigned int n)
{
assert(n <= points_.size());
for (unsigned int i = 0; i < n; i++) {
int num_points = points_.size();
Adjacencies& a = adjacency_vector_.back();
// Iterate over neighbors of this currently-being-deleted point
for (Adjacencies::iterator adj_iter = a.begin(); adj_iter != a.end(); adj_iter++) {
assert(adj_iter->neighbor < num_points);
Adjacencies& neighbor_adjacency_list = adjacency_vector_[adj_iter->neighbor];
// Iterate over neighbors of the neighbor
for (Adjacencies::iterator neighbor_adj_iter = neighbor_adjacency_list.begin(); neighbor_adj_iter
!= neighbor_adjacency_list.end(); neighbor_adj_iter++) {
// When we find the entry for the current point, remove it and exit inner loop
if (neighbor_adj_iter->neighbor == num_points - 1) {
neighbor_adjacency_list.erase(neighbor_adj_iter);
break;
}
}
}
adjacency_vector_.pop_back();
pointIds_.erase(points_.back());
points_.pop_back();
}
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::setCost(const Coords& c1, const Coords& c2)
{
setCost(c1, c2, c1.heuristicDistanceTo(c2));
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::setCost(const Coords& c1, const Coords& c2, int cost)
{
// Figure out indices of the given points
typename std::map<Coords, int>::iterator i1 = pointIds_.find(c1);
typename std::map<Coords, int>::iterator i2 = pointIds_.find(c2);
int index1 = i1->second;
int index2 = i2->second;
// Loop over which direction edge to add
for (unsigned int j = 0; j < 2; j++) {
int ind1, ind2;
if (j == 0) {
ind1 = index1;
ind2 = index2;
}
else {
ind1 = index2;
ind2 = index1;
}
// Now set cost of edge from ind1 to ind2
Adjacencies& adj = adjacency_vector_[ind1];
AdjListIterator i, last = adj.end();
for (i = adj.begin(); (i != last) && (i->neighbor != ind2); i++)
;
// If edge does not exist add it, else just set the cost of the existing edge
if (i == last) {
Adjacency a;
a.neighbor = ind2;
a.cost = cost;
adj.insert(i, a);
}
else {
i->cost = cost;
}
}
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::setStartState(const Coords& c)
{
typename std::map<Coords, int>::iterator i = pointIds_.find(c);
assert(i != pointIds_.end());
startStateId_ = i->second;
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::setGoalState(const Coords& c)
{
typename std::map<Coords, int>::iterator i = pointIds_.find(c);
assert(i != pointIds_.end());
goalStateId_ = i->second;
}
template<class Coords>
bool AdjacencyListSBPLEnv<Coords>::InitializeMDPCfg(MDPConfig *MDPCfg)
{
MDPCfg->goalstateid = goalStateId_;
MDPCfg->startstateid = startStateId_;
return true;
}
template<class Coords>
int AdjacencyListSBPLEnv<Coords>::GetFromToHeuristic(int FromStateID, int ToStateID)
{
return points_[FromStateID].heuristicDistanceTo(points_[ToStateID]);
}
template<class Coords>
int AdjacencyListSBPLEnv<Coords>::GetGoalHeuristic(int stateID)
{
return GetFromToHeuristic(stateID, goalStateId_);
}
template<class Coords>
int AdjacencyListSBPLEnv<Coords>::GetStartHeuristic(int stateID)
{
return GetFromToHeuristic(startStateId_, stateID);
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::PrintState(int stateID, bool bVerbose, FILE* fOut)
{
// Note we're ignoring the fOut argument
std::cout << points_[stateID] << endl;
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::PrintEnv_Config(FILE* fOut)
{
// Note we're ignoring the fOut argument
std::cout << "Adjacency list env" << endl;
}
template<class Coords>
int AdjacencyListSBPLEnv<Coords>::SizeofCreatedEnv()
{
return points_.size();
}
template<class Coords>
bool AdjacencyListSBPLEnv<Coords>::InitializeEnv(const char* sEnvFile)
{
// Nothing to do in initialization
return true;
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::SetAllActionsandAllOutcomes(CMDPSTATE* state)
{
// goal state is absorbing
if (state->StateID == goalStateId_) {
return;
}
Adjacencies& v = adjacency_vector_[state->StateID];
int actionIndex = 0;
for (AdjListIterator i = v.begin(); i != v.end(); i++) {
CMDPACTION* action = state->AddAction(actionIndex);
action->AddOutcome(i->neighbor, i->cost, 1.0);
}
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::SetAllPreds(CMDPSTATE* state)
{
throw SBPL_Exception("Error: SetAllPreds not implemented for adjacency list");
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV)
{
SuccIDV->clear();
CostV->clear();
if (SourceStateID == goalStateId_) {
return;
}
Adjacencies& v = adjacency_vector_[SourceStateID];
for (AdjListIterator i = v.begin(); i != v.end(); i++) {
SuccIDV->push_back(i->neighbor);
CostV->push_back(i->cost);
}
}
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::GetPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV)
{
throw SBPL_Exception("Error: GetPreds not currently implemented for adjacency list");
}
template<class Coords>
std::vector<Coords> AdjacencyListSBPLEnv<Coords>::findOptimalPath(int* solution_cost)
{
// Initialize ARA planner
ARAPlanner p(this, true);
p.set_start(startStateId_);
p.set_goal(goalStateId_);
p.set_initialsolution_eps(1.0);
std::vector<int> solution;
p.replan(1.0, &solution, solution_cost);
std::vector<Coords> solutionPoints;
for (unsigned int i = 0; i < solution.size(); i++) {
solutionPoints.push_back(points_[solution[i]]);
}
resetStateId2IndexMapping();
return solutionPoints;
}
// There's some side effect where you have to reset this every time you call the ARA planner
template<class Coords>
void AdjacencyListSBPLEnv<Coords>::resetStateId2IndexMapping(void)
{
for (unsigned int i = 0; i < StateID2IndexMapping.size(); i++) {
for (unsigned int j = 0; j < NUMOFINDICES_STATEID2IND; j++) {
StateID2IndexMapping[i][j] = -1;
}
}
}
#endif
// Local variables:
// mode:c++
// End:

View File

@@ -0,0 +1,232 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ENVIRONMENT_ROBARM_H_
#define __ENVIRONMENT_ROBARM_H_
#include <cstdio>
#include <sbpl/discrete_space_information/environment.h>
#define NUMOFLINKS 6
//for R* max. distance in coord to a sample point. It should be exactly this,
//for one of the coordinates and this or smaller for the rest
#define ROBARM_LONGACTIONDIST_CELLS 30
//# of random successors at distance defined above, used by R* search
#define ROBARM_NUMOFRANDSUCCSATDIST 10
//if cleared then the intersection of the whole arm against obstacles
//and bounds is checked
#define ENDEFF_CHECK_ONLY 0
#define UNIFORM_COST 1 //all the actions have the same costs when set
#define INVALID_NUMBER 999
class CMDPSTATE;
class MDPConfig;
typedef struct
{
short unsigned int x;
short unsigned int y;
bool bIsObstacle;
} CELLV;
//state structure
typedef struct STATE2D_t
{
unsigned int g;
short unsigned int iterationclosed;
short unsigned int x;
short unsigned int y;
} State2D;
typedef struct ENV_ROBARM_CONFIG
{
double EnvWidth_m;
double EnvHeight_m;
int EnvWidth_c;
int EnvHeight_c;
int BaseX_c;
short unsigned int EndEffGoalX_c;
short unsigned int EndEffGoalY_c;
double LinkLength_m[NUMOFLINKS];
double LinkStartAngles_d[NUMOFLINKS];
double LinkGoalAngles_d[NUMOFLINKS];
char** Grid2D;
double GridCellWidth;
double angledelta[NUMOFLINKS];
int anglevals[NUMOFLINKS];
} EnvROBARMConfig_t;
typedef struct ENVROBARMHASHENTRY
{
int stateID;
//state coordinates
short unsigned int coord[NUMOFLINKS];
short unsigned int endeffx;
short unsigned int endeffy;
} EnvROBARMHashEntry_t;
typedef struct
{
EnvROBARMHashEntry_t* goalHashEntry;
EnvROBARMHashEntry_t* startHashEntry;
//Maps from coords to stateId
int HashTableSize;
std::vector<EnvROBARMHashEntry_t*>* Coord2StateIDHashTable;
//vector that maps from stateID to coords
std::vector<EnvROBARMHashEntry_t*> StateID2CoordTable;
//any additional variables
int** Heur; //h[fromx][fromy][tox][toy] = Heur[to][from], where to= tox+toy*width_c, from = fromx+fromy*width_c
} EnvironmentROBARM_t;
/**
* \brief planar kinematic robot arm of variable number of degrees of freedom
*/
class EnvironmentROBARM : public DiscreteSpaceInformation
{
public:
/**
* \brief initialize environment from a file (see .cfg files in robotarm directory for example)
*/
virtual bool InitializeEnv(const char* sEnvFile);
/**
* \brief initialize MDP config with IDs of start/goal
*/
virtual bool InitializeMDPCfg(MDPConfig *MDPCfg);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetFromToHeuristic(int FromStateID, int ToStateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetGoalHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual int GetStartHeuristic(int stateID);
/**
* \brief see comments on the same function in the parent class
*/
virtual void SetAllActionsandAllOutcomes(CMDPSTATE* state);
/**
* \brief see comments on the same function in the parent class
*/
virtual void SetAllPreds(CMDPSTATE* state);
/**
* \brief see comments on the same function in the parent class
*/
virtual void GetSuccs(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CostV);
/**
* \brief see comments on the same function in the parent class
*/
virtual void GetPreds(int TargetStateID, std::vector<int>* PredIDV, std::vector<int>* CostV);
/**
* \brief see comments on the same function in the parent class
*/
virtual int SizeofCreatedEnv();
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintState(int stateID, bool bVerbose, FILE* fOut = NULL);
/**
* \brief see comments on the same function in the parent class
*/
virtual void PrintEnv_Config(FILE* fOut);
~EnvironmentROBARM() { }
protected:
//member data
EnvROBARMConfig_t EnvROBARMCfg;
EnvironmentROBARM_t EnvROBARM;
virtual void ComputeContAngles(short unsigned int coord[NUMOFLINKS], double angle[NUMOFLINKS]);
virtual void ComputeCoord(double angle[NUMOFLINKS], short unsigned int coord[NUMOFLINKS]);
virtual int ComputeEndEffectorPos(double angles[NUMOFLINKS], short unsigned int* pX, short unsigned int* pY);
virtual int IsValidCoord(short unsigned int coord[NUMOFLINKS], char** Grid2D = NULL,
std::vector<CELLV>* pTestedCells = NULL);
virtual int distanceincoord(unsigned short* statecoord1, unsigned short* statecoord2);
virtual void ReInitializeState2D(State2D* state);
virtual void InitializeState2D(State2D* state, short unsigned int x, short unsigned int y);
virtual void Search2DwithQueue(State2D** statespace, int* HeurGrid, int searchstartx, int searchstarty);
virtual void Create2DStateSpace(State2D*** statespace2D);
virtual void Delete2DStateSpace(State2D*** statespace2D);
virtual void printangles(FILE* fOut, short unsigned int* coord, bool bGoal, bool bVerbose, bool bLocal);
virtual void DiscretizeAngles();
virtual void Cell2ContXY(int x, int y, double *pX, double *pY);
virtual void ContXY2Cell(double x, double y, short unsigned int* pX, short unsigned int *pY);
virtual int IsValidLineSegment(double x0, double y0, double x1, double y1, char **Grid2D,
std::vector<CELLV>* pTestedCells);
virtual void GetRandomSuccsatDistance(int SourceStateID, std::vector<int>* SuccIDV, std::vector<int>* CLowV);
virtual unsigned int GetHeurBasedonCoord(short unsigned int coord[NUMOFLINKS]);
virtual void PrintHeader(FILE* fOut);
virtual int cost(short unsigned int state1coord[], short unsigned int state2coord[]);
virtual void ReadConfiguration(FILE* fCfg);
virtual void InitializeEnvConfig();
virtual unsigned int GETHASHBIN(short unsigned int* coord, int numofcoord);
virtual void PrintHashTableHist();
virtual EnvROBARMHashEntry_t* GetHashEntry(short unsigned int* coord, int numofcoord, bool bIsGoal);
virtual EnvROBARMHashEntry_t* CreateNewHashEntry(short unsigned int* coord, int numofcoord,
short unsigned int endeffx, short unsigned int endeffy);
virtual bool InitializeEnvironment();
virtual void ComputeHeuristicValues();
virtual int GetEdgeCost(int FromStateID, int ToStateID);
virtual int GetRandomState();
virtual bool AreEquivalent(int State1ID, int State2ID);
virtual void PrintSuccGoal(int SourceStateID, int costtogoal, bool bVerbose, bool bLocal /*=false*/,
FILE* fOut /*=NULL*/);
};
#endif

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __HEADERS_H_
#define __HEADERS_H_
#include <sbpl/sbpl_exception.h>
#include <sbpl/config.h>
#if MEM_CHECK == 1
#define _CRTDBG_MAP_ALLOC
#define CRTDBG_MAP_ALLOC
#endif
#include <stdlib.h> //have to go after the defines above
#if MEM_CHECK == 1
#include <crtdbg.h>
#endif
#include <sbpl/discrete_space_information/environment.h>
#include <sbpl/discrete_space_information/environment_nav2D.h>
#include <sbpl/discrete_space_information/environment_nav2Duu.h>
#include <sbpl/discrete_space_information/environment_navxythetalat.h>
#include <sbpl/discrete_space_information/environment_navxythetamlevlat.h>
#include <sbpl/discrete_space_information/environment_robarm.h>
#include <sbpl/discrete_space_information/environment_XXX.h>
#include <sbpl/heuristics/heuristic.h>
#include <sbpl/heuristics/embedded_heuristic.h>
#include <sbpl/planners/adplanner.h>
#include <sbpl/planners/ANAplanner.h>
#include <sbpl/planners/araplanner.h>
#include <sbpl/planners/mhaplanner.h>
#include <sbpl/planners/planner.h>
#include <sbpl/planners/ppcpplanner.h>
#include <sbpl/planners/rstarplanner.h>
#include <sbpl/planners/viplanner.h>
#include <sbpl/planners/lazyARA.h>
#include <sbpl/utils/2Dgridsearch.h>
#include <sbpl/utils/heap.h>
#include <sbpl/utils/list.h>
#include <sbpl/utils/key.h>
#include <sbpl/utils/mdp.h>
#include <sbpl/utils/mdpconfig.h>
#include <sbpl/utils/sbpl_fifo.h>
#include <sbpl/utils/sbpl_bfs_2d.h>
#include <sbpl/utils/sbpl_bfs_3d.h>
#include <sbpl/utils/utils.h>
#endif

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2015, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef sbpl_EmbeddedHeuristic_h
#define sbpl_EmbeddedHeuristic_h
#include <sbpl/heuristics/heuristic.h>
class EmbeddedHeuristic : public Heuristic
{
public:
EmbeddedHeuristic(DiscreteSpaceInformation* environment);
int GetGoalHeuristic(int state_id);
int GetStartHeuristic(int state_id);
int GetFromToHeuristic(int from_id, int to_id);
};
#endif

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2015, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef sbpl_Heuristic_h
#define sbpl_Heuristic_h
#include <sbpl/discrete_space_information/environment.h>
class Heuristic
{
public:
Heuristic(DiscreteSpaceInformation* environment) :
m_environment(environment)
{ }
virtual ~Heuristic() { }
virtual int GetGoalHeuristic(int state_id) = 0;
virtual int GetStartHeuristic(int state_id) = 0;
virtual int GetFromToHeuristic(int from_id, int to_id) = 0;
protected:
DiscreteSpaceInformation* m_environment;
};
#endif

View File

@@ -0,0 +1,272 @@
/*
* This code was used for generating experimental data for the purpose of understanding the performance of
* the Anytime Nonparametric A* (ANA*) algorithm.
* The authors of this algorithm are Jur van den Berg, Rajat Shah, Arthur Huang and Ken Goldberg.
* The code is available at http://goldberg.berkeley.edu/ana/
*
*/
#ifndef __anaPLANNER_H_
#define __anaPLANNER_H_
#include <cstdio>
#include <ctime>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/mdp.h>
//---configuration----
//control of EPS
//initial suboptimality bound (cost solution <= cost(eps*cost optimal solution)
#define ana_DEFAULT_INITIAL_EPS 100000.0
//as planning time exist, ana* decreases epsilon bound
#define ana_DECREASE_EPS 0.2
//final epsilon bound
#define ana_FINAL_EPS 1.0
//---------------------
#define ana_INCONS_LIST_ID 0
class CHeap;
class DiscreteSpaceInformation;
class StateChangeQuery;
//-------------------------------------------------------------
/**
* \brief state structure used in ana* search tree
*/
typedef class anaSEARCHSTATEDATA : public AbstractSearchState
{
public:
/**
* \brief the MDP state itself
*/
CMDPSTATE* MDPstate;
/**
* \brief ana* relevant data
*/
unsigned int v;
/**
* \brief ana* relevant data
*/
unsigned int g;
/**
* \brief ana* relevant data
*/
short unsigned int iterationclosed;
/**
* \brief ana* relevant data
*/
short unsigned int callnumberaccessed;
/**
* \brief ana* relevant data
*/
short unsigned int numofexpands;
/**
* \brief best predecessor and the action from it, used only in forward searches
*/
CMDPSTATE *bestpredstate;
/**
* \brief the next state if executing best action
*/
CMDPSTATE *bestnextstate;
unsigned int costtobestnextstate;
int h;
public:
anaSEARCHSTATEDATA() { }
~anaSEARCHSTATEDATA() { }
} anaState;
/**
* \brief the statespace of ana*
*/
typedef struct anaSEARCHSTATESPACE
{
unsigned int G;
double eps;
double eps_satisfied;
CHeap* heap;
short unsigned int searchiteration;
short unsigned int callnumber;
CMDPSTATE* searchgoalstate;
CMDPSTATE* searchstartstate;
CMDP searchMDP;
bool bReevaluatefvals;
bool bReinitializeSearchStateSpace;
bool bNewSearchIteration;
} anaSearchStateSpace_t;
/**
* \brief ana* planner
*/
class anaPlanner : public SBPLPlanner
{
public:
/**
* \brief replan a path within the allocated time, return the solution in the vector
*/
int replan(double allocated_time_secs, std::vector<int>* solution_stateIDs_V);
/**
* \brief replan a path within the allocated time, return the solution in
* the vector, also returns solution cost
*/
int replan(double allocated_time_sec, std::vector<int>* solution_stateIDs_V, int* solcost);
/**
* \brief set the goal state
*/
int set_goal(int goal_stateID);
/**
* \brief set the start state
*/
int set_start(int start_stateID);
/**
* \brief inform the search about the new edge costs
*/
void costs_changed(StateChangeQuery const & stateChange);
/**
* \brief inform the search about the new edge costs -
* \note since ana* is non-incremental, it is sufficient (and more
* efficient) to just inform ana* of the fact that some costs changed
*/
void costs_changed();
/**
* \brief set a flag to get rid of the previous search efforts, release
* the memory and re-initialize the search, when the next replan is called
*/
int force_planning_from_scratch();
/**
* \brief you can either search forwards or backwards
*/
int set_search_mode(bool bSearchUntilFirstSolution);
/**
* \brief returns the suboptimality bound on the currently found solution
*/
virtual double get_solution_eps() const { return pSearchStateSpace_->eps_satisfied; }
/**
* \brief returns the number of states expanded so far
*/
virtual int get_n_expands() const { return searchexpands; }
/**
* \brief returns the value of the initial epsilon (suboptimality bound) used
*/
virtual void set_initialsolution_eps(double initialsolution_eps) { finitial_eps = initialsolution_eps; }
/**
* \brief prints out the search path into a file
*/
void print_searchpath(FILE* fOut);
/**
* \brief constructor
*/
anaPlanner(DiscreteSpaceInformation* environment, bool bforwardsearch);
/**
* \brief destructor
*/
~anaPlanner();
private:
//member variables
double finitial_eps;
MDPConfig* MDPCfg_;
bool bforwardsearch; //if true, then search proceeds forward, otherwise backward
bool bsearchuntilfirstsolution; //if true, then search until first solution only (see planner.h for search modes)
anaSearchStateSpace_t* pSearchStateSpace_;
unsigned int searchexpands;
int MaxMemoryCounter;
clock_t TimeStarted;
FILE *fDeb;
void Initialize_searchinfo(CMDPSTATE* state, anaSearchStateSpace_t* pSearchStateSpace);
CMDPSTATE* CreateState(int stateID, anaSearchStateSpace_t* pSearchStateSpace);
CMDPSTATE* GetState(int stateID, anaSearchStateSpace_t* pSearchStateSpace);
int ComputeHeuristic(CMDPSTATE* MDPstate, anaSearchStateSpace_t* pSearchStateSpace);
//initialization of a state
void InitializeSearchStateInfo(anaState* state, anaSearchStateSpace_t* pSearchStateSpace);
//re-initialization of a state
void ReInitializeSearchStateInfo(anaState* state, anaSearchStateSpace_t* pSearchStateSpace);
void DeleteSearchStateData(anaState* state);
// NEW FUNCTION
double get_e_value(anaSearchStateSpace_t* pSearchStateSpace, int stateID);
//used for backward search
void UpdatePreds(anaState* state, anaSearchStateSpace_t* pSearchStateSpace);
//used for forward search
void UpdateSuccs(anaState* state, anaSearchStateSpace_t* pSearchStateSpace);
int GetGVal(int StateID, anaSearchStateSpace_t* pSearchStateSpace);
//returns 1 if the solution is found, 0 if the solution does not exist and 2 if it ran out of time
int ImprovePath(anaSearchStateSpace_t* pSearchStateSpace, double MaxNumofSecs);
void BuildNewOPENList(anaSearchStateSpace_t* pSearchStateSpace);
void Reevaluatefvals(anaSearchStateSpace_t* pSearchStateSpace);
//creates (allocates memory) search state space
//does not initialize search statespace
int CreateSearchStateSpace(anaSearchStateSpace_t* pSearchStateSpace);
//deallocates memory used by SearchStateSpace
void DeleteSearchStateSpace(anaSearchStateSpace_t* pSearchStateSpace);
//debugging
void PrintSearchState(anaState* state, FILE* fOut);
//reset properly search state space
//needs to be done before deleting states
int ResetSearchStateSpace(anaSearchStateSpace_t* pSearchStateSpace);
//initialization before each search
void ReInitializeSearchStateSpace(anaSearchStateSpace_t* pSearchStateSpace);
//very first initialization
int InitializeSearchStateSpace(anaSearchStateSpace_t* pSearchStateSpace);
int SetSearchGoalState(int SearchGoalStateID, anaSearchStateSpace_t* pSearchStateSpace);
int SetSearchStartState(int SearchStartStateID, anaSearchStateSpace_t* pSearchStateSpace);
//reconstruct path functions are only relevant for forward search
int ReconstructPath(anaSearchStateSpace_t* pSearchStateSpace);
void PrintSearchPath(anaSearchStateSpace_t* pSearchStateSpace, FILE* fOut);
int getHeurValue(anaSearchStateSpace_t* pSearchStateSpace, int StateID);
//get path
std::vector<int> GetSearchPath(anaSearchStateSpace_t* pSearchStateSpace, int& solcost);
bool Search(anaSearchStateSpace_t* pSearchStateSpace, std::vector<int>& pathIds, int & PathCost, bool bFirstSolution,
bool bOptimalSolution, double MaxNumofSecs);
};
#endif

View File

@@ -0,0 +1,371 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ADPLANNER_H_
#define __ADPLANNER_H_
#include <cstdio>
#include <ctime>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/key.h>
#include <sbpl/utils/mdp.h>
//---configuration----
//control of EPS
//initial suboptimality bound (cost solution <= cost(eps*cost optimal solution)
#define AD_DEFAULT_INITIAL_EPS 10.0
//as planning time exist, AD* decreases epsilon bound
#define AD_DECREASE_EPS 0.2
//final epsilon bound
#define AD_FINAL_EPS 1.0
//---------------------
#define AD_INCONS_LIST_ID 0
class CHeap;
class CList;
class DiscreteSpaceInformation;
class MDPConfig;
class StateChangeQuery;
//-------------------------------------------------------------
/**
* \brief generic state structure in the search tree generated by AD*
*/
typedef class ADSEARCHSTATEDATA : public AbstractSearchState
{
public:
/**
* \brief the MDP state itself (pointer to the graph represented as MDPstates)
*/
CMDPSTATE* MDPstate;
/**
* \brief AD* relevant data
*/
unsigned int v;
/**
* \brief AD* relevant data
*/
unsigned int g;
/**
* \brief AD* relevant data
*/
short unsigned int iterationclosed;
/**
* \brief AD* relevant data
*/
short unsigned int callnumberaccessed;
#if DEBUG
/**
* \brief AD* relevant data
*/
short unsigned int numofexpands;
#endif
/** \brief best predecessor and the action from it, used only in forward searches
*/
CMDPSTATE *bestpredstate;
/** \brief the next state if executing best action
*/
CMDPSTATE *bestnextstate;
unsigned int costtobestnextstate;
int h;
public:
ADSEARCHSTATEDATA() { }
~ADSEARCHSTATEDATA() { }
} ADState;
/**
* \brief statespace of AD*
*/
typedef struct ADSEARCHSTATESPACE
{
double eps;
double eps_satisfied;
CHeap* heap;
CList* inconslist;
short unsigned int searchiteration;
short unsigned int callnumber;
CMDPSTATE* searchgoalstate;
CMDPSTATE* searchstartstate;
CMDP searchMDP;
bool bReevaluatefvals;
bool bReinitializeSearchStateSpace;
bool bRebuildOpenList;
} ADSearchStateSpace_t;
/**
* \brief Anytime D* search planner: all states are uniquely defined by stateIDs
*/
class ADPlanner : public SBPLPlanner
{
public:
/**
* \brief replan a path within the allocated time, return the solution in the vector
*/
virtual int replan(double allocated_time_secs, std::vector<int>* solution_stateIDs_V);
/**
* \brief replan a path within the allocated time, return the solution in
* the vector, also returns solution cost
*/
virtual int replan(double allocated_time_secs, std::vector<int>* solution_stateIDs_V, int* solcost);
/**
* \brief works same as replan function with time and solution states, but
* it let's you fill out all the parameters for the search
*/
virtual int replan(std::vector<int>* solution_stateIDs_V, ReplanParams params);
/**
* \brief works same as replan function with time, solution states, and
* cost, but it let's you fill out all the parameters for the search
*/
virtual int replan(std::vector<int>* solution_stateIDs_V, ReplanParams params, int* solcost);
/**
* \brief set the goal state
*/
virtual int set_goal(int goal_stateID);
/**
* \brief set the start state
*/
virtual int set_start(int start_stateID);
/**
* \brief set a flag to get rid of the previous search efforts, and
* re-initialize the search, when the next replan is called
*/
virtual int force_planning_from_scratch();
/**
* \brief Gets rid of the previous search efforts, release the memory and
* re-initialize the search.
*/
virtual int force_planning_from_scratch_and_free_memory();
/**
* \brief you can either search forwards or backwards
*/
virtual int set_search_mode(bool bSearchUntilFirstSolution);
/**
* \brief inform the search about the new edge costs
*/
virtual void costs_changed(StateChangeQuery const & stateChange);
/**
* \brief direct form of informing the search about the new edge costs
*
* \param succsIDV array of successors of changed edges
* \note this is used when the search is run forwards
*/
virtual void update_succs_of_changededges(std::vector<int>* succsIDV);
/**
* \brief direct form of informing the search about the new edge costs
*
* \param predsIDV array of predecessors of changed edges
* \note this is used when the search is run backwards
*/
virtual void update_preds_of_changededges(std::vector<int>* predsIDV);
/**
* \brief returns the suboptimality bound on the currently found solution
*/
virtual double get_solution_eps() const { return pSearchStateSpace_->eps_satisfied; }
/**
* \brief returns the number of states expanded so far
*/
virtual int get_n_expands() const { return searchexpands; }
/**
* \brief returns the initial epsilon
*/
virtual double get_initial_eps() { return finitial_eps; }
/**
* \brief returns the time taken to find the first solution
*/
virtual double get_initial_eps_planning_time() { return finitial_eps_planning_time; }
/**
* \brief returns the time taken to get the final solution
*/
virtual double get_final_eps_planning_time() { return final_eps_planning_time; }
/**
* \brief returns the number of expands to find the first solution
*/
virtual int get_n_expands_init_solution() { return num_of_expands_initial_solution; }
/**
* \brief returns the final epsilon achieved during the search
*/
virtual double get_final_epsilon() { return final_eps; }
/**
* \brief returns the value of the initial epsilon (suboptimality bound) used
*/
virtual void set_initialsolution_eps(double initialsolution_eps) { finitial_eps = initialsolution_eps; }
/**
* \brief fills out a vector of stats from the search
*/
virtual void get_search_stats(std::vector<PlannerStats>* s);
/**
* \brief constructor
*/
ADPlanner(DiscreteSpaceInformation* environment, bool bForwardSearch);
/**
* \brief destructor
*/
~ADPlanner();
protected:
//member variables
double finitial_eps, finitial_eps_planning_time, final_eps_planning_time, final_eps, dec_eps, final_epsilon;
double repair_time;
bool use_repair_time;
int num_of_expands_initial_solution;
MDPConfig* MDPCfg_;
std::vector<PlannerStats> stats;
bool bforwardsearch;
bool bsearchuntilfirstsolution; //if true, then search until first solution (see planner.h for search modes)
ADSearchStateSpace_t* pSearchStateSpace_;
unsigned int searchexpands;
int MaxMemoryCounter;
clock_t TimeStarted;
FILE *fDeb;
//member functions
virtual void Initialize_searchinfo(CMDPSTATE* state, ADSearchStateSpace_t* pSearchStateSpace);
virtual CMDPSTATE* CreateState(int stateID, ADSearchStateSpace_t* pSearchStateSpace);
virtual CMDPSTATE* GetState(int stateID, ADSearchStateSpace_t* pSearchStateSpace);
virtual int ComputeHeuristic(CMDPSTATE* MDPstate, ADSearchStateSpace_t* pSearchStateSpace);
//initialization of a state
virtual void InitializeSearchStateInfo(ADState* state, ADSearchStateSpace_t* pSearchStateSpace);
//re-initialization of a state
virtual void ReInitializeSearchStateInfo(ADState* state, ADSearchStateSpace_t* pSearchStateSpace);
virtual void DeleteSearchStateData(ADState* state);
//used for backward search
virtual void UpdatePredsofOverconsState(ADState* state, ADSearchStateSpace_t* pSearchStateSpace);
virtual void UpdatePredsofUnderconsState(ADState* state, ADSearchStateSpace_t* pSearchStateSpace);
//used for forward search
virtual void UpdateSuccsofOverconsState(ADState* state, ADSearchStateSpace_t* pSearchStateSpace);
virtual void UpdateSuccsofUnderconsState(ADState* state, ADSearchStateSpace_t* pSearchStateSpace);
virtual void UpdateSetMembership(ADState* state);
virtual void Recomputegval(ADState* state);
virtual int GetGVal(int StateID, ADSearchStateSpace_t* pSearchStateSpace);
//returns 1 if the solution is found, 0 if the solution does not exist and 2 if it ran out of time
virtual int ComputePath(ADSearchStateSpace_t* pSearchStateSpace, double MaxNumofSecs);
virtual void BuildNewOPENList(ADSearchStateSpace_t* pSearchStateSpace);
virtual void Reevaluatefvals(ADSearchStateSpace_t* pSearchStateSpace);
virtual void Reevaluatehvals(ADSearchStateSpace_t* pSearchStateSpace);
//creates (allocates memory) search state space
//does not initialize search statespace
virtual int CreateSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace);
//deallocates memory used by SearchStateSpace
virtual void DeleteSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace);
//reset properly search state space
//needs to be done before deleting states
virtual int ResetSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace);
//initialization before each search
virtual void ReInitializeSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace);
//very first initialization
virtual int InitializeSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace);
virtual int SetSearchGoalState(int SearchGoalStateID, ADSearchStateSpace_t* pSearchStateSpace);
virtual int SetSearchStartState(int SearchStartStateID, ADSearchStateSpace_t* pSearchStateSpace);
//reconstruct path functions are only relevant for forward search
virtual int ReconstructPath(ADSearchStateSpace_t* pSearchStateSpace);
virtual void PrintSearchState(ADState* searchstateinfo, FILE* fOut);
virtual void PrintSearchPath(ADSearchStateSpace_t* pSearchStateSpace, FILE* fOut);
virtual int getHeurValue(ADSearchStateSpace_t* pSearchStateSpace, int StateID);
//get path
virtual std::vector<int> GetSearchPath(ADSearchStateSpace_t* pSearchStateSpace, int& solcost);
virtual bool Search(ADSearchStateSpace_t* pSearchStateSpace, std::vector<int>& pathIds, int & PathCost,
bool bFirstSolution, bool bOptimalSolution, double MaxNumofSecs);
virtual CKey ComputeKey(ADState* state);
virtual void Update_SearchSuccs_of_ChangedEdges(std::vector<int> const * statesIDV);
};
/**
* \brief See comments in sbpl/src/planners/planner.h about the what and why of
* this class.
*/
class StateChangeQuery
{
public:
virtual ~StateChangeQuery() { }
virtual std::vector<int> const * getPredecessors() const = 0;
virtual std::vector<int> const * getSuccessors() const = 0;
};
#endif

View File

@@ -0,0 +1,368 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ARAPLANNER_H_
#define __ARAPLANNER_H_
#include <cstdio>
#include <ctime>
#include <vector>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/mdp.h>
//---configuration----
//control of EPS
//initial suboptimality bound (cost solution <= cost(eps*cost optimal solution)
#define ARA_DEFAULT_INITIAL_EPS 5.0
//as planning time exist, ARA* decreases epsilon bound
#define ARA_DECREASE_EPS 0.2
//final epsilon bound
#define ARA_FINAL_EPS 1.0
//---------------------
#define ARA_INCONS_LIST_ID 0
class CHeap;
class CList;
class DiscreteSpaceInformation;
class MDPConfig;
class StateChangeQuery;
//-------------------------------------------------------------
/**
* \brief state structure used in ARA* search tree
*/
typedef class ARASEARCHSTATEDATA : public AbstractSearchState
{
public:
/**
* \brief the MDP state itself
*/
CMDPSTATE* MDPstate;
/**
* \brief ARA* relevant data
*/
unsigned int v;
/**
* \brief ARA* relevant data
*/
unsigned int g;
/**
* \brief ARA* relevant data
*/
short unsigned int iterationclosed;
/**
* \brief ARA* relevant data
*/
short unsigned int callnumberaccessed;
#if DEBUG
/**
* \brief ARA* relevant data
*/
short unsigned int numofexpands;
#endif
/**
* \brief best predecessor and the action from it, used only in forward searches
*/
CMDPSTATE *bestpredstate;
/**
* \brief the next state if executing best action
*/
CMDPSTATE *bestnextstate;
unsigned int costtobestnextstate;
int h;
public:
ARASEARCHSTATEDATA() { }
~ARASEARCHSTATEDATA() { }
} ARAState;
/**
* \brief the statespace of ARA*
*/
typedef struct ARASEARCHSTATESPACE
{
double eps;
double eps_satisfied;
CHeap* heap;
CList* inconslist;
short unsigned int searchiteration;
short unsigned int callnumber;
CMDPSTATE* searchgoalstate;
CMDPSTATE* searchstartstate;
CMDP searchMDP;
bool bReevaluatefvals;
bool bReinitializeSearchStateSpace;
bool bNewSearchIteration;
} ARASearchStateSpace_t;
/**
* \brief ARA* planner
*/
class ARAPlanner : public SBPLPlanner
{
public:
/**
* \brief replan a path within the allocated time, return the solution in the vector
*/
virtual int replan(double allocated_time_secs, std::vector<int>* solution_stateIDs_V);
/**
* \brief replan a path within the allocated time, return the solution in the vector, also returns solution cost
*/
virtual int replan(double allocated_time_sec, std::vector<int>* solution_stateIDs_V, int* solcost);
/**
* \brief works same as replan function with time and solution states, but
* it let's you fill out all the parameters for the search
*/
virtual int replan(std::vector<int>* solution_stateIDs_V, ReplanParams params);
/**
* \brief works same as replan function with time, solution states, and
* cost, but it let's you fill out all the parameters for the search
*/
virtual int replan(std::vector<int>* solution_stateIDs_V, ReplanParams params, int* solcost);
/**
* \brief set the goal state
*/
virtual int set_goal(int goal_stateID);
/**
* \brief set the start state
*/
virtual int set_start(int start_stateID);
/**
* \brief inform the search about the new edge costs
*/
virtual void costs_changed(StateChangeQuery const & stateChange);
/**
* \brief inform the search about the new edge costs -
* \note since ARA* is non-incremental, it is sufficient (and more
* efficient) to just inform ARA* of the fact that some costs changed
*/
virtual void costs_changed();
/**
* \brief set a flag to get rid of the previous search efforts, and
* re-initialize the search, when the next replan is called
*/
virtual int force_planning_from_scratch();
/**
* \brief Gets rid of the previous search efforts, release the memory and re-initialize the search.
*/
virtual int force_planning_from_scratch_and_free_memory();
/**
* \brief you can either search forwards or backwards
*/
virtual int set_search_mode(bool bSearchUntilFirstSolution);
/**
* \brief returns the suboptimality bound on the currently found solution
*/
virtual double get_solution_eps() const { return pSearchStateSpace_->eps_satisfied; }
/**
* \brief returns the number of states expanded so far
*/
virtual int get_n_expands() const { return searchexpands; }
/**
* \brief sets the value of the initial epsilon (suboptimality bound) used
*/
virtual void set_initialsolution_eps(double initialsolution_eps) { finitial_eps = initialsolution_eps; }
/**
* \brief sets the value to decrease from eps at each iteration
*/
virtual void set_eps_step(double eps) { dec_eps = eps; }
/**
* \brief prints out the search path into a file
*/
virtual void print_searchpath(FILE* fOut);
/**
* \brief Compute the suboptimality bound for the most recent solution.
*
* The suboptimality bound of the solution may be provably less than the
* value of epsilon satisfied during the most recent planning iteration.
* This suboptimality bound is computed as the ratio between the current
* g-value for the goal and the minimum un-weighted f-value of a locally
* inconsistent state.
*
* \return The suboptimality bound of the most recently computed solution
*/
double compute_suboptimality();
/**
* \brief constructor
*/
ARAPlanner(DiscreteSpaceInformation* environment, bool bforwardsearch);
/**
* \brief destructor
*/
~ARAPlanner();
/**
* \brief returns the initial epsilon
*/
virtual double get_initial_eps() { return finitial_eps; }
/**
* \brief returns the time taken to find the first solution
*/
virtual double get_initial_eps_planning_time() { return finitial_eps_planning_time; }
/**
* \brief returns the time taken to get the final solution
*/
virtual double get_final_eps_planning_time() { return final_eps_planning_time; }
/**
* \brief Return the number of expands to find the first solution or -1 if no solution has been found.
*/
virtual int get_n_expands_init_solution() { return num_of_expands_initial_solution; }
/**
* \brief returns the final epsilon achieved during the search
*/
virtual double get_final_epsilon() { return final_eps; }
/**
* \brief fills out a vector of stats from the search
*/
virtual void get_search_stats(std::vector<PlannerStats>* s);
protected:
//member variables
double finitial_eps, finitial_eps_planning_time, final_eps_planning_time, final_eps, dec_eps, final_epsilon;
double repair_time;
bool use_repair_time;
std::vector<PlannerStats> stats;
int num_of_expands_initial_solution;
MDPConfig* MDPCfg_;
bool bforwardsearch; //if true, then search proceeds forward, otherwise backward
bool bsearchuntilfirstsolution; //if true, then search until first solution only (see planner.h for search modes)
ARASearchStateSpace_t* pSearchStateSpace_;
unsigned int searchexpands;
int MaxMemoryCounter;
clock_t TimeStarted;
FILE *fDeb;
//member functions
virtual void Initialize_searchinfo(CMDPSTATE* state, ARASearchStateSpace_t* pSearchStateSpace);
virtual CMDPSTATE* CreateState(int stateID, ARASearchStateSpace_t* pSearchStateSpace);
virtual CMDPSTATE* GetState(int stateID, ARASearchStateSpace_t* pSearchStateSpace);
virtual int ComputeHeuristic(CMDPSTATE* MDPstate, ARASearchStateSpace_t* pSearchStateSpace);
//initialization of a state
virtual void InitializeSearchStateInfo(ARAState* state, ARASearchStateSpace_t* pSearchStateSpace);
//re-initialization of a state
virtual void ReInitializeSearchStateInfo(ARAState* state, ARASearchStateSpace_t* pSearchStateSpace);
virtual void DeleteSearchStateData(ARAState* state);
//used for backward search
virtual void UpdatePreds(ARAState* state, ARASearchStateSpace_t* pSearchStateSpace);
//used for forward search
virtual void UpdateSuccs(ARAState* state, ARASearchStateSpace_t* pSearchStateSpace);
virtual int GetGVal(int StateID, ARASearchStateSpace_t* pSearchStateSpace);
//returns 1 if the solution is found, 0 if the solution does not exist and 2 if it ran out of time
virtual int ImprovePath(ARASearchStateSpace_t* pSearchStateSpace, double MaxNumofSecs);
virtual void BuildNewOPENList(ARASearchStateSpace_t* pSearchStateSpace);
virtual void Reevaluatefvals(ARASearchStateSpace_t* pSearchStateSpace);
virtual void Reevaluatehvals(ARASearchStateSpace_t* pSearchStateSpace);
//creates (allocates memory) search state space
//does not initialize search statespace
virtual int CreateSearchStateSpace(ARASearchStateSpace_t* pSearchStateSpace);
//deallocates memory used by SearchStateSpace
virtual void DeleteSearchStateSpace(ARASearchStateSpace_t* pSearchStateSpace);
//debugging
virtual void PrintSearchState(ARAState* state, FILE* fOut);
//reset properly search state space
//needs to be done before deleting states
virtual int ResetSearchStateSpace(ARASearchStateSpace_t* pSearchStateSpace);
//initialization before each search
virtual void ReInitializeSearchStateSpace(ARASearchStateSpace_t* pSearchStateSpace);
//very first initialization
virtual int InitializeSearchStateSpace(ARASearchStateSpace_t* pSearchStateSpace);
virtual int SetSearchGoalState(int SearchGoalStateID, ARASearchStateSpace_t* pSearchStateSpace);
virtual int SetSearchStartState(int SearchStartStateID, ARASearchStateSpace_t* pSearchStateSpace);
//reconstruct path functions are only relevant for forward search
virtual int ReconstructPath(ARASearchStateSpace_t* pSearchStateSpace);
virtual void PrintSearchPath(ARASearchStateSpace_t* pSearchStateSpace, FILE* fOut);
virtual int getHeurValue(ARASearchStateSpace_t* pSearchStateSpace, int StateID);
//get path
virtual std::vector<int> GetSearchPath(ARASearchStateSpace_t* pSearchStateSpace, int& solcost);
virtual bool Search(ARASearchStateSpace_t* pSearchStateSpace, std::vector<int>& pathIds, int & PathCost,
bool bFirstSolution, bool bOptimalSolution, double MaxNumofSecs);
};
#endif

View File

@@ -0,0 +1,191 @@
/*
* Copyright (c) 2013, Mike Phillips and Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LAZY_ARA_PLANNER_H_
#define _LAZY_ARA_PLANNER_H_
#include "../../sbpl/headers.h"
#include <queue>
class LazyListElement;
class LazyARAState: public AbstractSearchState
{
public:
int id;
unsigned int v;
unsigned int g;
int h;
short unsigned int iteration_closed;
short unsigned int replan_number;
LazyARAState* best_parent;
LazyARAState* expanded_best_parent;
bool in_incons;
std::priority_queue<LazyListElement> lazyList;
bool isTrueCost;
};
class LazyListElement
{
public:
LazyListElement(LazyARAState* p, int ec, bool itc)
{
parent = p;
edgeCost = ec;
isTrueCost = itc;
}
bool operator< (const LazyListElement& other) const
{
return (parent->v + edgeCost > other.parent->v + other.edgeCost);
}
LazyARAState* parent;
int edgeCost;
bool isTrueCost;
};
class LazyARAPlanner : public SBPLPlanner
{
public:
virtual int replan(double allocated_time_secs, std::vector<int>* solution_stateIDs_V);
virtual int replan(double allocated_time_sec, std::vector<int>* solution_stateIDs_V, int* solcost);
virtual int replan(int start, int goal, std::vector<int>* solution_stateIDs_V, ReplanParams params, int* solcost);
virtual int replan(std::vector<int>* solution_stateIDs_V, ReplanParams params);
virtual int replan(std::vector<int>* solution_stateIDs_V, ReplanParams params, int* solcost);
virtual int set_goal(int goal_stateID);
virtual int set_start(int start_stateID);
virtual void costs_changed(StateChangeQuery const & stateChange) { return; }
virtual void costs_changed() { return; }
virtual int force_planning_from_scratch() { return 1; }
virtual int force_planning_from_scratch_and_free_memory()
{
freeMemory();
return 1;
}
virtual int set_search_mode(bool bSearchUntilFirstSolution)
{
params.return_first_solution = bSearchUntilFirstSolution;
return 1;
}
virtual void set_initialsolution_eps(double initialsolution_eps)
{
params.initial_eps = initialsolution_eps;
}
LazyARAPlanner(DiscreteSpaceInformation* environment, bool bforwardsearch);
~LazyARAPlanner();
virtual void get_search_stats(std::vector<PlannerStats>* s);
double get_initial_eps() {
if (stats.empty()) return -1; return stats.front().eps;
}
double get_solution_eps() const {
if (stats.empty()) return -1; return stats.back().eps;
}
double get_final_epsilon() {
if (stats.empty()) return -1; return stats.back().eps;
}
double get_initial_eps_planning_time() {
if (stats.empty()) return -1; return stats.front().time;
}
double get_final_eps_planning_time() {
if (stats.empty()) return -1; return totalPlanTime;
}
int get_n_expands_init_solution() {
if (stats.empty()) return -1; return stats.front().expands;
}
int get_n_expands() const {
if (stats.empty()) return -1; return totalExpands;
}
protected:
// data structures (open and incons lists)
CHeap heap;
std::vector<LazyARAState*> incons;
std::vector<LazyARAState*> states;
// params
ReplanParams params;
bool bforwardsearch; // if true, then search proceeds forward, otherwise backward
LazyARAState* goal_state;
LazyARAState* start_state;
int goal_state_id;
int start_state_id;
// search member variables
double eps;
double eps_satisfied;
int search_expands;
clock_t TimeStarted;
short unsigned int search_iteration;
short unsigned int replan_number;
bool use_repair_time;
// stats
std::vector<PlannerStats> stats;
unsigned int totalExpands;
double totalTime;
double totalPlanTime;
double reconstructTime;
virtual LazyARAState* GetState(int id);
virtual void ExpandState(LazyARAState* parent);
virtual void EvaluateState(LazyARAState* parent);
void getNextLazyElement(LazyARAState* state);
void insertLazyList(LazyARAState* state, LazyARAState* parent, int edgeCost, bool isTrueCost);
void putStateInHeap(LazyARAState* state);
void freeMemory();
virtual int ImprovePath();
virtual std::vector<int> GetSearchPath(int& solcost);
virtual bool outOfTime();
virtual void initializeSearch();
virtual void prepareNextSearchIteration();
virtual bool Search(std::vector<int>& pathIds, int & PathCost);
};
#endif

View File

@@ -0,0 +1,214 @@
/*
* Copyright (c) 2015, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef sbpl_MHAPlanner_h
#define sbpl_MHAPlanner_h
#include <sbpl/heuristics/heuristic.h>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/heap.h>
struct MHASearchState
{
int call_number;
int state_id;
int g;
MHASearchState* bp;
bool closed_in_anc;
bool closed_in_add;
struct HeapData
{
AbstractSearchState open_state;
int h;
};
HeapData od[1]; // overallocated for additional n heuristics
};
class MHAPlanner : public SBPLPlanner
{
public:
MHAPlanner(
DiscreteSpaceInformation* environment,
Heuristic* hanchor,
Heuristic** heurs,
int hcount);
virtual ~MHAPlanner();
virtual int set_start(int start_stateID);
virtual int set_goal(int goal_stateID);
/// \sa SBPLPlanner::replan(double, std::vector<int>*)
virtual int replan(
double allocated_time_sec,
std::vector<int>* solution_stateIDs_V);
/// \sa SBPLPlanner::replan(double, std::vector<int>*, int*)
virtual int replan(
double allocated_time_sec,
std::vector<int>* solution_stateIDs_V,
int* solcost);
/// \sa SBPLPlanner::replan(std::vector<int*>, ReplanParams)
virtual int replan(
std::vector<int>* solution_stateIDs_V,
ReplanParams params);
/// \sa SBPLPlanner::replan(std::vector<int>*, ReplanParams, int*)
virtual int replan(
std::vector<int>* solution_stateIDs_V,
ReplanParams params,
int* solcost);
/// \sa SBPLPlanner::force_planning_from_scratch()
/// \return 1 on success; 0 otherwise
virtual int force_planning_from_scratch();
/// \sa SBPLPlanner::force_planning_from_scratch_and_free_memory()
/// \return 1 on success; 0 otherwise
virtual int force_planning_from_scratch_and_free_memory();
virtual void costs_changed(StateChangeQuery const & stateChange);
/// \sa ARAPlanner::costs_changed()
virtual void costs_changed();
/// \name Search Parameter Accessors
///@{
/// \sa SBPLPlanner::set_search_mode(bool)
virtual int set_search_mode(bool bSearchUntilFirstSolution);
/// \sa SBPLPlanner::set_initialsolution_eps(double)
virtual void set_initialsolution_eps(double eps);
/// \sa SBPLPlanner::get_initial_eps()
virtual double get_initial_eps();
///@}
/// \name Search Statistics
///@{
/// \sa SBPLPlanner::get_solution_eps() const
virtual double get_solution_eps() const;
/// \sa SBPLPlanner::get_final_epsilon()
virtual double get_final_epsilon();
/// \sa SBPLPlanner::get_final_eps_planning_time
virtual double get_final_eps_planning_time();
/// \sa SBPLPlanner::get_initial_eps_planning_time
virtual double get_initial_eps_planning_time();
/// \sa SBPLPlanner::get_n_expands() const
virtual int get_n_expands() const;
///\sa SBPLPlanner::get_n_expands_init_solution()
virtual int get_n_expands_init_solution();
/// \sa SBPLPlanner::get_search_states(std::vector<PlannerStates>*)
virtual void get_search_stats(std::vector<PlannerStats>* s);
///@}
/// \name Homogeneous accessor methods for search mode and timing parameters
// @{
void set_initial_eps(double eps) { return set_initialsolution_eps(eps); }
void set_initial_mha_eps(double eps_mha);
void set_final_eps(double eps);
void set_dec_eps(double eps);
void set_max_expansions(int expansion_count);
void set_max_time(double max_time);
// double get_initial_eps();
double get_initial_mha_eps() const;
double get_final_eps() const;
double get_dec_eps() const;
int get_max_expansions() const;
double get_max_time() const;
///@}
private:
// Related objects
Heuristic* m_hanchor;
Heuristic** m_heurs;
int m_hcount; ///< number of additional heuristics used
ReplanParams m_params;
double m_initial_eps_mha;
int m_max_expansions;
double m_eps; ///< current w_1
double m_eps_mha; ///< current w_2
/// suboptimality bound satisfied by the last search
double m_eps_satisfied;
int m_num_expansions; ///< current number of expansion
double m_elapsed; ///< current amount of seconds
int m_call_number;
MHASearchState* m_start_state;
MHASearchState* m_goal_state;
std::vector<MHASearchState*> m_search_states;
CHeap* m_open; ///< sequence of (m_hcount + 1) open lists
bool check_params(const ReplanParams& params);
bool time_limit_reached() const;
int num_heuristics() const { return m_hcount + 1; }
MHASearchState* get_state(int state_id);
void init_state(MHASearchState* state, size_t mha_state_idx, int state_id);
void reinit_state(MHASearchState* state);
void reinit_search();
void clear_open_lists();
void clear();
int compute_key(MHASearchState* state, int hidx);
void expand(MHASearchState* state, int hidx);
MHASearchState* state_from_open_state(AbstractSearchState* open_state);
int compute_heuristic(int state_id, int hidx);
int get_minf(CHeap& pq) const;
void insert_or_update(MHASearchState* state, int hidx, int f);
void extract_path(std::vector<int>* solution_path, int* solcost);
bool closed_in_anc_search(MHASearchState* state) const;
bool closed_in_add_search(MHASearchState* state) const;
bool closed_in_any_search(MHASearchState* state) const;
};
#endif

View File

@@ -0,0 +1,351 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __PLANNER_H_
#define __PLANNER_H_
#include <cstddef>
#include <vector>
#include <sbpl/config.h>
#define GETSTATEIND(stateid, mapid) StateID2IndexMapping[mapid][stateid]
//indices for the StateID2Index mapping
enum STATEID2IND
{
STATEID2IND_SLOT0 = 0, STATEID2IND_SLOT1,//add more slots if necessary
NUMOFINDICES_STATEID2IND
};
//use the slots above for the mutually exclusive algorithms
#define VIMDP_STATEID2IND STATEID2IND_SLOT0
#define ARAMDP_STATEID2IND STATEID2IND_SLOT0
#define ADMDP_STATEID2IND STATEID2IND_SLOT0
#define RSTARMDP_STATEID2IND STATEID2IND_SLOT0
#define RSTARMDP_LSEARCH_STATEID2IND STATEID2IND_SLOT1
#define anaMDP_STATEID2IND STATEID2IND_SLOT0
#define MHAMDP_STATEID2IND STATEID2IND_SLOT0
//for example
//#define YYYPLANNER_STATEID2IND STATEID2IND_SLOT0
//#define YYYPLANNER_STATEID2IND STATEID2IND_SLOT1
class DiscreteSpaceInformation;
/**
* Utility for unified notification of cost changes
* across all SBPLPlanner subtypes. Ideally we would have a simple
* unified interface, such as std::vector<nav2dcell_t>, but the
* current separation of planner and environment representation code
* would be violated if we just included that here.
* At the moment, ADPlanner is the only one who really uses the
* detailed information provided by ChangedCellsGetter, so we define
* that class in sbpl/src/planners/ADStar/adplanner.h (to be moved up
* the hierarchy when we generalize).
*/
class StateChangeQuery;
/**
* \brief a parameter class for planners
*/
class ReplanParams
{
public:
/**
* \brief constructor which sets some default values for the parameters
* \param time The maximum planning time
*/
ReplanParams(double time)
{
max_time = time;
initial_eps = 5.0;
final_eps = 1.0;
dec_eps = 0.2;
return_first_solution = false;
repair_time = -1;
}
/**
* \brief the initial epsilon. (for anytime planners) the default value is 5.0
*/
double initial_eps;
/**
* \brief the final epsilon. (for anytime planners) the default value is 1.0 (optimal solution)
*/
double final_eps;
/**
* \brief the amount epsilon decreases by between searches. (for anytime planners) By default this is 0.2
*/
double dec_eps;
/**
* \brief should the planner return after the finding first solution?
* (this will cause the planner to ignore all time limits) By default this
* is false.
*/
bool return_first_solution;
/**
* \brief The planner will use all of this time planning unless it reaches
* a solution for final_eps before the time is up
*/
double max_time;
/**
* \brief If this time out is not positive, it is ignored (this is the
* default). If the planner finds a first solution (in under maxTime of
* course) the time out for the planner becomes the minimum of maxTime and
* repairTime (clearly repairTime is useless if it is larger than
* maxTime). This second timer is useful because you often want a
* solution in a short amount of time (repairTime) where you are willing
* to let the planner improve the solution, but you are willing to wait a
* longer amount of time (maxTime) to get the first solution.
*/
double repair_time;
};
class PlannerStats
{
public:
double eps;
int cost;
double time;
int expands;
};
typedef enum
{
//different state types if you have more than one type inside a single planner
ABSTRACT_STATE = 0, ABSTRACT_STATEACTIONPAIR, ABSTRACT_GENERALSTATE
} AbstractSearchStateType_t;
/**
* \brief base class for a search state
*/
class AbstractSearchState
{
public:
/**
* \brief each state can be a member of at most two lists
* indices of lists are given in planner.h (e.g., STATEID2IND_SLOT0)
*/
struct listelement* listelem[2];
/**
* \brief index of the state in the heap, typically used for membership in OPEN
*/
int heapindex;
/**
* \brief type of state. usually it will be general state
*/
AbstractSearchStateType_t StateType;
public:
AbstractSearchState()
{
StateType = ABSTRACT_GENERALSTATE;
listelem[0] = listelem[1] = NULL;
}
~AbstractSearchState() { }
};
/**
* \brief pure virtual base class for a generic planner
*/
class SBPLPlanner
{
public:
/**
* \brief returns 1 if solution is found, 0 otherwise will replan
* incrementally if possible (e.g., as supported by the planner and not
* forced to replan from scratch) takes in the time available for planner
* and returns a sequence of stateIDs that corresponds to the solution
*/
virtual int replan(double allocated_time_sec, std::vector<int>* solution_stateIDs_V) = 0;
/**
* \brief works same as replan function with two parameters, but also returns the cost of the solution
*/
virtual int replan(double allocated_time_sec, std::vector<int>* solution_stateIDs_V, int* solcost) = 0;
/**
* \brief works same as replan function with time and solution states, but
* it let's you fill out all the parameters for the search
*/
virtual int replan(std::vector<int>* solution_stateIDs_V, ReplanParams params)
{
SBPL_ERROR("replan using ReplanParams is unimplemented for this planner\n");
return 0;
}
/**
* \brief works same as replan function with time, solution states, and
* cost, but it let's you fill out all the parameters for the search
*/
virtual int replan(std::vector<int>* solution_stateIDs_V, ReplanParams params, int* solcost)
{
SBPL_ERROR("replan using ReplanParams is unimplemented for this planner\n");
return 0;
}
/**
* \brief sets the goal of search (planner will automatically decide whether it needs to replan from scratch)
*/
virtual int set_goal(int goal_stateID) = 0;
/**
* \brief sets the start of search (planner will automatically decide whether it needs to replan from scratch)
*/
virtual int set_start(int start_stateID) = 0;
/**
* \brief forgets previous planning efforts and starts planning from scratch next time replan is called
*/
virtual int force_planning_from_scratch() = 0;
/**
* \brief forgets previous planning efforts and starts planning from scratch next time replan is called
*/
virtual int force_planning_from_scratch_and_free_memory()
{
SBPL_ERROR("planning from scratch and free memory is unimplemented for this planner\n");
return 0;
}
/**
* \brief sets the mode for searching
*
* if bSearchUntilFirstSolution is false, then planner searches for at most
* allocatime_time_sec, independently of whether it finds a solution or not
* (default mode) if bSearchUntilFirstSolution is true, then planner
* searches until it finds the first solution. It may be faster than
* allocated_time or it may be longer In other words, in the latter case,
* the planner does not spend time on improving the solution even if time
* permits, but may also take longer than allocated_time before returning
* So, normally bSearchUntilFirstSolution should be set to false.
*/
virtual int set_search_mode(bool bSearchUntilFirstSolution) = 0;
/**
* \brief Notifies the planner that costs have changed. May need to be
* specialized for different subclasses in terms of what to
* do here
*/
virtual void costs_changed(StateChangeQuery const & stateChange) = 0;
/**
* \return The "epsilon" value of the solution last computed by
* replan(), if such an epsilon is used by the planner. The base class
* implementation returns -1 to express that it has no such thing.
*/
virtual double get_solution_eps() const
{
SBPL_ERROR("get_solution_eps is unimplemented for this planner\n");
return -1;
}
/**
* \return The number of states expanded during the last replan()
* operation, or -1 if this information is not available.
*/
virtual int get_n_expands() const
{
SBPL_ERROR("get_n_expands is unimplemented for this planner\n");
return -1;
}
/**
* \brief returns the initial epsilon
*/
virtual double get_initial_eps()
{
SBPL_ERROR("get_initial_eps is unimplemented for this planner\n");
return -1;
}
/**
* \brief returns the time taken to find the first solution
*/
virtual double get_initial_eps_planning_time()
{
SBPL_ERROR("get_initial_eps_planning_time is unimplemented for this planner\n");
return -1;
}
/**
* \brief returns the time taken to get the final solution
*/
virtual double get_final_eps_planning_time()
{
SBPL_ERROR("get_final_eps_planning_time is unimplemented for this planner\n");
return -1;
}
/**
* \brief returns the number of expands to find the first solution
*/
virtual int get_n_expands_init_solution()
{
SBPL_ERROR("get_n_expands_init_solution is unimplemented for this planner\n");
return -1;
}
/**
* \brief returns the final epsilon achieved during the search
*/
virtual double get_final_epsilon()
{
SBPL_ERROR("get_final_epsilon is unimplemented for this planner\n");
return -1;
}
/**
* \brief fills out a vector of stats from the search
*/
virtual void get_search_stats(std::vector<PlannerStats>* s)
{
SBPL_ERROR("get_search_stats is unimplemented for this planner\n");
}
/**
* \brief setting initial solution eps
* This parameter is ignored in planners that don't have a notion of eps
* In ARA* / AD*: (cost(initialsolution) <= eps*cost(optimalsolution))
*/
virtual void set_initialsolution_eps(double initialsolution_eps) { }
virtual ~SBPLPlanner() { }
protected:
DiscreteSpaceInformation *environment_;
};
#endif

View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 2009, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __PPCPPLANNER_H_
#define __PPCPPLANNER_H_
#include <cstdio>
#include <sbpl/sbpl_exception.h>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/mdp.h>
#include <sbpl/utils/utils.h>
class DiscreteSpaceInformation;
class StateChangeQuery;
/**
* \brief a state for PPCP
*/
typedef class PPCPPLANNERSTATEDATA : public AbstractSearchState
{
public:
/**
* \brief the MDP state itself
*/
CMDPSTATE* MDPstate;
/**
* \brief planner relevant data
*/
int v;
/**
* \brief planner relevant data
*/
unsigned int iteration;
/**
* \brief best action
*/
CMDPACTION *bestnextaction;
private:
//probability of reaching this state (intermediate variable used by the algorithm)
float Pc;
public:
PPCPPLANNERSTATEDATA() { }
~PPCPPLANNERSTATEDATA() { }
} PPCPState;
/**
* \brief PPCP statespace
*/
typedef struct PPCPSTATESPACE
{
/**
* \brief MDP
*/
CMDP MDP;
/**
* \brief pointer to start state
*/
CMDPSTATE* StartState;
/**
* \brief pointer to goal state
*/
CMDPSTATE* GoalState;
int iteration;
int searchiteration;
//TODO - vector<PolicyFullState_t*> CurrentPolicy; //current policy
double currentpolicyconfidence;
/**
* \brief set when it is necessary to reset the planner
*/
bool bReinitializeSearchStateSpace;
} PPCPStateSpace_t;
/**
* \brief PPCP planner
* in explanations, S signifies a fully observable part of the state space H
* signifies hidden variables
*/
class PPCPPlanner : public SBPLPlanner
{
public:
/**
* \brief planning (replanning) function. Takes in time available for
* planning
*
* returns policy, expected cost of the solution policy, and probability of
* successfully reaching the goal (it is < 1, whenever PPCP ran out of time
* before full convergence
*/
int replan(double allocated_time_secs, std::vector<sbpl_PolicyStatewithBinaryh_t>* SolutionPolicy,
float* ExpectedCost, float* ProbofReachGoal);
/**
* \brief constructors
*/
PPCPPlanner(DiscreteSpaceInformation* environment, int sizeofS, int sizeofH);
/**
* \brief destructor
*/
~PPCPPlanner();
/**
* \brief setting goal state in S
*/
int set_goal(int goal_stateID);
/**
* \brief setting start state in S
*/
int set_start(int start_stateID);
/**
* \brief not supported version of replan
*/
int replan(double allocated_time_sec, std::vector<int>* solution_stateIDs_V)
{
throw SBPL_Exception("ERROR: this version of replan not supported in PPCP planner");
}
/**
* \brief not supported version of replan
*/
int replan(double allocated_time_sec, std::vector<int>* solution_stateIDs_V, int* solcost)
{
throw SBPL_Exception("ERROR: this version of replan not supported in PPCP planner");
}
/**
* \brief forgets previous planning efforts and starts planning from scratch next time replan is called
*/
int force_planning_from_scratch();
/**
* \brief sets how to search - not supported in PPCP
*/
int set_search_mode(bool bSearchUntilFirstSolution)
{
throw SBPL_Exception("ERROR: set_search_mode not supported in PPCP planner");
}
/**
* \brief Notifies the planner that costs have changed. May need to be
* specialized for different subclasses in terms of what to
* do here
*/
void costs_changed(StateChangeQuery const & stateChange);
/**
* \brief notifies the planner that costs have changed
*/
void costs_changed();
private:
//member variables
PPCPStateSpace_t* pStateSpace;
FILE* fDeb;
//deallocates memory used by SearchStateSpace
void DeleteStateSpace(PPCPStateSpace_t* pStateSpace);
int CreateSearchStateSpace(PPCPStateSpace_t* pStateSpace);
};
#endif

View File

@@ -0,0 +1,479 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __RSTARPLANNER_H_
#define __RSTARPLANNER_H_
#include <cstdio>
#include <ctime>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/heap.h>
#include <sbpl/utils/key.h>
#include <sbpl/utils/mdp.h>
//---configuration----
//control of EPS
#define RSTAR_DEFAULT_INITIAL_EPS 3.0
#define RSTAR_DECREASE_EPS 0.2
#define RSTAR_FINAL_EPS 1.0
//the number of states to expand for local search in RSTAR before it declares a hard case and postpones its processing
#define RSTAR_EXPTHRESH 1000
//---------------------
#define RSTAR_INCONS_LIST_ID 0
class CList;
class StateChangeQuery;
//-------------------------------------------------------------
/**
* \brief high level states in R* search
* \note in other words, state structure for high level states in Gamma graph
*/
typedef class RSTARSEARCHSTATEDATA : public AbstractSearchState
{
public:
/**
* \brief the MDP state itself
*/
CMDPSTATE* MDPstate;
/**
* \brief RSTAR* relevant data
*/
unsigned int g;
/**
* \brief RSTAR* relevant data
*/
short unsigned int iterationclosed;
/**
* \brief RSTAR* relevant data
*/
short unsigned int callnumberaccessed;
/**
* \brief best predecessor and the action from it
*
* \note note that in R* bestpredaction refers to best predecessor in the
* high-level graph constructed by R* this graph is ALWAYS rooted at
* searchstart and directed towards searchgoal independently of the actual
* direction of search (from start to goal or from goal to start) thus
* sourcestate for the action is always at the state closer to the start of
* the search tree
*/
CMDPACTION *bestpredaction;
/**
* \brief set of predecessor actions together with some info
*/
std::vector<CMDPACTION*> predactionV;
/**
* \brief RSTAR* relevant data - heuristics
*/
int h;
public:
RSTARSEARCHSTATEDATA() { }
~RSTARSEARCHSTATEDATA() { }
} RSTARState;
/**
* \brief action in Gamma graph. Each action in Gamma graph corresponds to a path
*/
typedef struct RSTARACTIONDATA_T
{
/**
* \brief lower bound on the cost of the path
*/
int clow;
/**
* \brief number of expansions done so far to compute the path that represents this action
*/
int exp;
/**
* \brief path that the action represents
*
* \note the path is always stored as a valid path w.r.t. the original graph
* (not search tree) so if the search is forward, then the path is from
* source to target and otherwise, the path is from target toward source
*/
std::vector<int> pathIDs;
} RSTARACTIONDATA;
/**
* \brief low-level (local) search state in R*
*/
typedef class RSTARLSEARCHSTATEDATA : public AbstractSearchState
{
public:
/**
* \brief the MDP state itself
*/
CMDPSTATE* MDPstate;
/**
* \brief planner relevant data - g-value
*/
int g;
/**
* \brief planner relevant data
*/
unsigned int iteration;
/**
* \brief planner relevant data
*/
unsigned int iterationclosed;
/**
* \brief best predecessors according to the search tree (so, in backward search these are actual successors)
*/
CMDPSTATE* bestpredstate;
/**
* \brief the cost of the best action from the best preds to this state
*/
int bestpredstateactioncost;
public:
RSTARLSEARCHSTATEDATA() { }
~RSTARLSEARCHSTATEDATA() { }
} RSTARLSearchState;
/**
* \brief local search statespace in R*
*/
class RSTARLSEARCHSTATESPACE
{
public:
/**
* \brief graph constructed by local search
*/
CMDP MDP;
/**
* \brief start state
*/
CMDPSTATE* StartState;
/**
* \brief goal state
*/
CMDPSTATE* GoalState;
/**
* \brief search-related variable
*/
int iteration;
/**
* \brief open list
*/
CHeap* OPEN;
/**
* \brief incons list - used for suboptimal search
*/
CList* INCONS;
public:
RSTARLSEARCHSTATESPACE()
{
OPEN = NULL;
INCONS = NULL;
StartState = NULL;
GoalState = NULL;
}
~RSTARLSEARCHSTATESPACE()
{
if (OPEN != NULL) delete OPEN;
}
};
typedef class RSTARLSEARCHSTATESPACE RSTARLSearchStateSpace_t;
/**
* \brief statespace
*/
typedef struct RSTARSEARCHSTATESPACE
{
/**
* \brief required epsilon
*/
double eps;
/**
* \brief epsilon that is satisfied
*/
double eps_satisfied;
/**
* \brief open list
*/
CHeap* OPEN;
/**
* \brief searchiteration gets incremented with every R* search (and reset upon every increment of callnumber)
*/
short unsigned int searchiteration;
/**
* \brief callnumber gets incremented with every call to R* (so, it can
* be multiple number of times within planning times since R* is executed
* multiple times)
*/
short unsigned int callnumber;
/**
* \brief search goal state (not necessarily the actual start state, it depends on search direction)
*/
CMDPSTATE* searchgoalstate;
/**
* \brief search start state
*/
CMDPSTATE* searchstartstate;
/**
* \brief graph constructed by high-level search
*/
CMDP searchMDP;
/**
* \brief need to reevaluate fvals
*/
bool bReevaluatefvals;
/**
* \brief need to reinitialize search space
*/
bool bReinitializeSearchStateSpace;
/**
* \brief set when it is a new search iteration
*/
bool bNewSearchIteration;
} RSTARSearchStateSpace_t;
/**
* \brief RSTAR* planner
*/
class RSTARPlanner : public SBPLPlanner
{
public:
/**
* \brief replan a path within the allocated time, return the solution in the vector
*/
int replan(double allocated_time_secs, std::vector<int>* solution_stateIDs_V);
/**
* \brief replan a path within the allocated time, return the solution in the vector, also returns solution cost
*/
int replan(double allocated_time_sec, std::vector<int>* solution_stateIDs_V, int* solcost);
/**
* \brief set the goal state
*/
int set_goal(int goal_stateID);
/**
* \brief set the start state
*/
int set_start(int start_stateID);
/**
* \brief inform the search about the new edge costs
*/
void costs_changed(StateChangeQuery const & stateChange);
/**
* \brief inform the search about the new edge costs -
*
* \note since R* is non-incremental, it is sufficient (and more efficient)
* to just inform R* of the fact that some costs changed
*/
void costs_changed();
/**
* \brief set a flag to get rid of the previous search efforts, release
* the memory and re-initialize the search, when the next replan is called
*/
int force_planning_from_scratch();
/**
* \brief you can either search forwards or backwards
*/
int set_search_mode(bool bSearchUntilFirstSolution);
/**
* \brief obtain probabilistic eps suboptimality bound
*/
virtual double get_solution_probabilisticeps() const { return pSearchStateSpace->eps_satisfied; }
/**
* \brief get number of high level expands
*/
virtual int get_highlevel_expands() const { return highlevel_searchexpands; }
/**
* \brief get number of low level expands
*/
virtual int get_lowlevel_expands() const { return lowlevel_searchexpands; }
/**
* \brief set initial solution epsilon that R* will try to satisfy (probabilistically)
*/
virtual void set_initialsolution_eps(double initialsolution_eps) { finitial_eps = initialsolution_eps; }
/**
* \brief sets the value to decrease from eps at each iteration
*/
virtual void set_eps_step(double eps) { dec_eps = eps; }
/**
* \brief sets the number of states to expand for local search in RSTAR before
* it declares a hard case and postpones its processing.
*/
virtual void set_local_expand_thres(unsigned thres) { local_expand_thres = thres; }
/**
* \brief returns the initial epsilon used by the search
*/
double get_initial_eps() { return finitial_eps; }
/**
* \brief returns the final epsilon achieved during the search
*/
double get_final_epsilon()
{
if (pSearchStateSpace != NULL)
return pSearchStateSpace->eps_satisfied;
else
return INFINITECOST;
}
/**
* \brief print out search path
*/
void print_searchpath(FILE* fOut);
/**
* \brief constructor
*/
RSTARPlanner(DiscreteSpaceInformation* environment, bool bforwardsearch);
/**
* \brief destructor
*/
~RSTARPlanner();
private:
//member variables
double finitial_eps;
double dec_eps;
double final_epsilon;
double local_expand_thres;
bool bforwardsearch; //if true, then search proceeds forward, otherwise backward
bool bsearchuntilfirstsolution; //if true, then search until first solution only (see planner.h for search modes)
RSTARSearchStateSpace_t* pSearchStateSpace;
RSTARLSearchStateSpace_t* pLSearchStateSpace;
unsigned int highlevel_searchexpands;
unsigned int lowlevel_searchexpands;
int MaxMemoryCounter;
clock_t TimeStarted;
FILE *fDeb;
//member functions
void Initialize_searchinfo(CMDPSTATE* state);
CMDPSTATE* CreateState(int stateID);
CMDPSTATE* GetState(int stateID);
int ComputeHeuristic(CMDPSTATE* MDPstate);
//initialization of a state
void InitializeSearchStateInfo(RSTARState* state);
//re-initialization of a state
void ReInitializeSearchStateInfo(RSTARState* state);
void DeleteSearchStateData(RSTARState* state);
void DeleteSearchActionData(RSTARACTIONDATA* actiondata);
int GetGVal(int StateID);
//returns 1 if the solution is found, 0 if the solution does not exist and 2 if it ran out of time
int ImprovePath(double MaxNumofSecs);
//note this does NOT re-compute heuristics, only re-orders OPEN list based on current eps and h-vals
void Reevaluatefvals();
//creates (allocates memory) search state space
//does not initialize search statespace
int CreateSearchStateSpace();
//deallocates memory used by SearchStateSpace
void DeleteSearchStateSpace();
//debugging
void PrintSearchState(RSTARState* state, FILE* fOut);
//reset properly search state space
//needs to be done before deleting states
int ResetSearchStateSpace();
//initialization before each search
void ReInitializeSearchStateSpace();
//very first initialization
int InitializeSearchStateSpace();
//setting start/goal
int SetSearchGoalState(int SearchGoalStateID);
int SetSearchStartState(int SearchStartStateID);
int getHeurValue(int StateID);
//get path
std::vector<int> GetSearchPath(int& solcost);
void PrintSearchPath(FILE* fOut);
//the actual search
bool Search(std::vector<int>& pathIds, int & PathCost, bool bFirstSolution, bool bOptimalSolution,
double MaxNumofSecs);
//local search
bool ComputeLocalPath(int StartStateID, int GoalStateID, int maxc, int maxe, int *pCost, int *pCostLow, int *pExp,
std::vector<int>* pPathIDs, int* pNewGoalStateID, double maxnumofsecs);
//global search functions
void SetBestPredecessor(RSTARState* rstarState, RSTARState* rstarPredState, CMDPACTION* action);
CKey ComputeKey(RSTARState* rstarState);
//local search functions
void Initialize_rstarlsearchdata(CMDPSTATE* state);
CMDPSTATE* CreateLSearchState(int stateID);
CMDPSTATE* GetLSearchState(int stateID);
bool DestroyLocalSearchMemory();
CKey LocalSearchComputeKey(RSTARLSearchState* rstarlsearchState);
};
#endif

View File

@@ -0,0 +1,131 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __VIPLANNER_H_
#define __VIPLANNER_H_
#include <cstdio>
#include <ctime>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/mdp.h>
#define MDP_ERRDELTA 0.01
class DiscreteSpaceInformation;
class MDPConfig;
struct VIPLANNER_T
{
CMDP MDP;
CMDPSTATE* StartState;
CMDPSTATE* GoalState;
int iteration;
};
/**
* \brief Value Iteration state
*/
typedef class VIPLANNERSTATEDATA : public AbstractSearchState
{
public:
/**
* \brief the MDP state itself
*/
CMDPSTATE* MDPstate;
/**
* \brief planner relevant data
*/
float v;
float Pc;
unsigned int iteration;
/**
* \brief best action
*/
CMDPACTION *bestnextaction;
public:
VIPLANNERSTATEDATA() { }
~VIPLANNERSTATEDATA() { }
} VIState;
/**
* \brief value iteration planner
*/
class VIPlanner : public SBPLPlanner
{
public:
/**
* \brief replan a path within the allocated time, return the policy in the solution vector
*/
virtual int replan(double allocated_time_secs, std::vector<int>* solution_stateIDs_V);
/**
* \brief constructors
*/
VIPlanner(DiscreteSpaceInformation* environment, MDPConfig* MDP_cfg)
{
environment_ = environment;
MDPCfg_ = MDP_cfg;
}
/**
* \brief destructor
*/
~VIPlanner();
protected:
//member variables
MDPConfig* MDPCfg_;
VIPLANNER_T viPlanner;
virtual void Initialize_vidata(CMDPSTATE* state);
virtual CMDPSTATE* CreateState(int stateID);
virtual CMDPSTATE* GetState(int stateID);
virtual void PrintVIData();
virtual void PrintStatHeader(FILE* fOut);
virtual void PrintStat(FILE* fOut, clock_t starttime);
virtual void PrintPolicy(FILE* fPolicy);
virtual void backup(CMDPSTATE* state);
virtual void perform_iteration_backward();
virtual void perform_iteration_forward();
virtual void InitializePlanner();
};
#endif

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SBPL_EXCEPTION_H
#define SBPL_EXCEPTION_H
#include <stdexcept>
#include <string>
#include <sbpl/config.h>
class SBPL_Exception : public std::runtime_error
{
public:
explicit SBPL_Exception(
const std::string& what_arg = "SBPL has encountered a fatal error!")
:
std::runtime_error(what_arg)
{
SBPL_ERROR("%s\n", what_arg.c_str());
}
explicit SBPL_Exception(const char* what_arg) :
std::runtime_error(what_arg)
{
SBPL_ERROR("%s\n", what_arg);
}
virtual ~SBPL_Exception() throw() { }
private:
};
#endif

View File

@@ -0,0 +1,233 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __2DGRIDSEARCH_H_
#define __2DGRIDSEARCH_H_
#include <cstdlib>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/key.h>
#include <sbpl/utils/utils.h>
#define SBPL_2DGRIDSEARCH_NUMOF2DDIRS 16
#define SBPL_2DSEARCH_OPEN_LIST_ID 0
// Forward declaration needed to allow instance of CIntHeap*
class CIntHeap;
class CSlidingBucket;
enum SBPL_2DGRIDSEARCH_TERM_CONDITION
{
SBPL_2DGRIDSEARCH_TERM_CONDITION_OPTPATHFOUND,
SBPL_2DGRIDSEARCH_TERM_CONDITION_20PERCENTOVEROPTPATH,
SBPL_2DGRIDSEARCH_TERM_CONDITION_TWOTIMESOPTPATH,
SBPL_2DGRIDSEARCH_TERM_CONDITION_THREETIMESOPTPATH,
SBPL_2DGRIDSEARCH_TERM_CONDITION_ALLCELLS
};
enum SBPL_2DGRIDSEARCH_OPENTYPE
{
SBPL_2DGRIDSEARCH_OPENTYPE_HEAP, SBPL_2DGRIDSEARCH_OPENTYPE_SLIDINGBUCKETS
};
//#define SBPL_2DGRIDSEARCH_HEUR2D(x,y) ((int)(1000*cellSize_m_*sqrt((double)((x-goalX_)*(x-goalX_)+(y-goalY_)*(y-goalY_)))))
#define SBPL_2DGRIDSEARCH_HEUR2D(x,y) ((int)(1000*cellSize_m_*__max(abs(x-goalX_),abs(y-goalY_))))
/**
* \brief search state corresponding to each 2D cell
*/
class SBPL_2DGridSearchState : public AbstractSearchState
{
public:
/**
* \brief coordinates
*/
int x, y;
/**
* \brief search relevant data
*/
int g;
/**
* \brief iteration at which the state was accessed (generated) last
*/
int iterationaccessed;
public:
SBPL_2DGridSearchState() { iterationaccessed = 0; }
~SBPL_2DGridSearchState() { }
};
/**
* \brief 2D search itself
*/
class SBPL2DGridSearch
{
public:
/**
* @brief SBPL2DGridSearch Create a search space for 2D grids
* @param width_x grid width
* @param height_y grid height
* @param cellsize_m resolution
* @param downsample edge length of block in main grid that corresponds to a single cell in this grid
* @param initial_dynamic_bucket_size Initial dynamic bucket size, set to 0 for fixed size
*/
SBPL2DGridSearch(int width_x, int height_y, float cellsize_m, int downsample=1, int initial_dynamic_bucket_size=32);
~SBPL2DGridSearch()
{
destroy();
}
/**
* \brief the priority data structure used - it affects efficiency (can be
* either heap or sliding buckets, see definition of
* SBPL_2DGRIDSEARCH_OPENTYPE)
*/
bool setOPENdatastructure(SBPL_2DGRIDSEARCH_OPENTYPE OPENtype);
/**
* \brief destroys the search and clears all memory
*/
void destroy();
/** \brief performs search itself. All costs are given as cost(cell1,
* cell2) = Euclidean distance*1000*(max(cell1,cell2)+1) for adjacent
* cells.
* \note It is infinite if max(cell1,cell2) >= obsthresh For cells that are
* not adjacent (which may happen if 16 connected grid is ON), then max is
* taken over all the cells center line goes through Search is done from
* start to goal. termination_condition specifies when to stop the search.
* In particular, one may specify to run it until OPEN is empty. In this
* case, the values of all states will be computed.
*/
bool search(unsigned char** Grid2D, unsigned char obsthresh, int startx_c, int starty_c, int goalx_c, int goaly_c,
SBPL_2DGRIDSEARCH_TERM_CONDITION termination_condition);
/**
* \brief print all the values
*/
void printvalues();
/**
* \brief returns the computed distance from the start to <x,y>. If not computed, then returns lower bound on it.
*/
inline int getlowerboundoncostfromstart_inmm(int x, int y)
{
x /= downsample_; // local x
y /= downsample_; // local y
if (term_condition_usedlast == SBPL_2DGRIDSEARCH_TERM_CONDITION_OPTPATHFOUND) {
//heuristic search
int h = SBPL_2DGRIDSEARCH_HEUR2D(x,y);
//the logic is that if s wasn't expanded, then g(s) + h(s) >=
//maxcomputed_fval => g(s) >= maxcomputed_fval - h(s)
return ((searchStates2D_[x][y].iterationaccessed == iteration_ &&
searchStates2D_[x][y].g + h <= largestcomputedoptf_) ? searchStates2D_[x][y].g :
largestcomputedoptf_ < INFINITECOST ? largestcomputedoptf_ - h :
INFINITECOST);
}
else {
//Dijkstra's search
//the logic is that if s wasn't expanded, then g(s) >= maxcomputed_fval => g(s) >= maxcomputed_fval - h(s)
return ((searchStates2D_[x][y].iterationaccessed == iteration_ &&
searchStates2D_[x][y].g <= largestcomputedoptf_) ? searchStates2D_[x][y].g :
largestcomputedoptf_);
}
}
/**
* \brief returns largest optimal g-value computed by search - a lower
* bound on the state values of unexpanded states
*/
int getlargestcomputedoptimalf_inmm() { return largestcomputedoptf_; }
private:
inline bool withinMap(int x, int y)
{
return (x >= 0 && y >= 0 && x < width_ && y < height_);
}
void computedxy();
inline void initializeSearchState2D(SBPL_2DGridSearchState* state2D);
bool createSearchStates2D(void);
/// Pointer to getCost function appropriate for resample size
unsigned char (*getCost)(unsigned char**, int, int, int);
bool search_withheap(unsigned char** Grid2D, unsigned char obsthresh, int startx_c, int starty_c, int goalx_c,
int goaly_c, SBPL_2DGRIDSEARCH_TERM_CONDITION termination_condition);
bool search_exp(unsigned char** Grid2D, unsigned char obsthresh, int startx_c, int starty_c, int goalx_c,
int goaly_c);
bool search_withbuckets(unsigned char** Grid2D, unsigned char obsthresh, int startx_c, int starty_c, int goalx_c,
int goaly_c);
bool search_withslidingbuckets(unsigned char** Grid2D, unsigned char obsthresh, int startx_c, int starty_c,
int goalx_c, int goaly_c, SBPL_2DGRIDSEARCH_TERM_CONDITION termination_condition);
//2D search data
int initial_dynamic_bucket_size_;
CSlidingBucket* OPEN2DBLIST_;
CIntHeap* OPEN2D_;
SBPL_2DGridSearchState** searchStates2D_;
int dx_[SBPL_2DGRIDSEARCH_NUMOF2DDIRS];
int dy_[SBPL_2DGRIDSEARCH_NUMOF2DDIRS];
//the intermediate cells through which the actions go
//(for all the ones with the first index <=7, there are none(they go to direct neighbors) -> initialized to -1)
int dx0intersects_[SBPL_2DGRIDSEARCH_NUMOF2DDIRS];
int dx1intersects_[SBPL_2DGRIDSEARCH_NUMOF2DDIRS];
int dy0intersects_[SBPL_2DGRIDSEARCH_NUMOF2DDIRS];
int dy1intersects_[SBPL_2DGRIDSEARCH_NUMOF2DDIRS];
//distances of transitions
int dxy_distance_mm_[SBPL_2DGRIDSEARCH_NUMOF2DDIRS];
//OPEN data structure type
SBPL_2DGRIDSEARCH_OPENTYPE OPENtype_;
//start and goal configurations
int startX_, startY_;
int goalX_, goalY_;
//map parameters
int width_, height_;
float cellSize_m_;
//search iteration
int iteration_;
// the size of the block edge in the main gid that corresponds to 1 cell in the 2D grid
int downsample_;
//largest optimal g-value computed by search
int largestcomputedoptf_;
//termination criterion used in the search
SBPL_2DGRIDSEARCH_TERM_CONDITION term_condition_usedlast;
};
#endif

View File

@@ -0,0 +1,139 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __HEAP_H_
#define __HEAP_H_
#include <sbpl/planners/planner.h>
#include <sbpl/utils/key.h>
//the maximum size of the heap
#define HEAPSIZE 20000000
#define HEAPSIZE_INIT 5000
struct HEAPELEMENT
{
AbstractSearchState *heapstate;
CKey key;
};
typedef struct HEAPELEMENT heapelement;
class CHeap
{
//data
public:
int percolates; //for counting purposes
heapelement* heap;
int currentsize;
int allocated;
//constructors
public:
CHeap();
~CHeap();
//functions
public:
bool emptyheap();
bool fullheap();
bool inheap(AbstractSearchState *AbstractSearchState);
CKey getkeyheap(AbstractSearchState *AbstractSearchState);
void makeemptyheap();
void insertheap(AbstractSearchState *AbstractSearchState, CKey key);
void deleteheap(AbstractSearchState *AbstractSearchState);
void updateheap(AbstractSearchState *AbstractSearchState, CKey NewKey);
AbstractSearchState *getminheap();
AbstractSearchState *getminheap(CKey& ReturnKey);
CKey getminkeyheap();
AbstractSearchState *deleteminheap();
void makeheap();
void insert_unsafe(AbstractSearchState* state, CKey key);
void updateheap_unsafe(AbstractSearchState* AbstractSearchState, CKey NewKey);
void deleteheap_unsafe(AbstractSearchState* AbstractSearchState);
private:
void percolatedown(int hole, heapelement tmp);
void percolateup(int hole, heapelement tmp);
void percolateupordown(int hole, heapelement tmp);
void growheap();
void sizecheck();
};
struct HEAPINTELEMENT
{
AbstractSearchState *heapstate;
int key;
};
typedef struct HEAPINTELEMENT heapintelement;
class CIntHeap
{
//data
public:
int percolates; //for counting purposes
heapintelement* heap;
int currentsize;
int allocated;
//constructors
public:
CIntHeap();
CIntHeap(int initial_size);
~CIntHeap();
//functions
public:
bool emptyheap();
bool fullheap();
bool inheap(AbstractSearchState *AbstractSearchState);
int getkeyheap(AbstractSearchState *AbstractSearchState);
void makeemptyheap();
void insertheap(AbstractSearchState *AbstractSearchState, int key);
void deleteheap(AbstractSearchState *AbstractSearchState);
void updateheap(AbstractSearchState *AbstractSearchState, int NewKey);
AbstractSearchState *getminheap();
AbstractSearchState *getminheap(int& ReturnKey);
int getminkeyheap();
AbstractSearchState *deleteminheap();
void makeheap();
private:
void percolatedown(int hole, heapintelement tmp);
void percolateup(int hole, heapintelement tmp);
void percolateupordown(int hole, heapintelement tmp);
void growheap();
void sizecheck();
};
#endif

View File

@@ -0,0 +1,184 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __KEY_H_
#define __KEY_H_
#define KEY_SIZE 2
#define INFINITECOST 1000000000
class CKey
{
//data
public:
long int key[KEY_SIZE];
//constructors
public:
CKey()
{
#if KEY_SIZE == 1
key[0] = 0;
#elif KEY_SIZE == 2
key[0] = 0;
key[1] = 0;
#else
for(int i = 0; i < KEY_SIZE; i++)
{
key[i] = 0;
}
#endif
}
~CKey() { }
//functions
public:
void SetKeytoInfinity()
{
for (int i = 0; i < KEY_SIZE; i++) {
key[i] = INFINITECOST;
}
}
void SetKeytoZero()
{
for (int i = 0; i < KEY_SIZE; i++) {
key[i] = 0;
}
}
void operator =(CKey RHSKey)
{
//iterate through the keys
//the 0ht is the most important key
#if KEY_SIZE == 1
key[0] = RHSKey.key[0];
#elif KEY_SIZE == 2
key[0] = RHSKey.key[0];
key[1] = RHSKey.key[1];
#else
for(int i = 0; i < KEY_SIZE; i++)
key[i] = RHSKey.key[i];
#endif
}
CKey operator -(const CKey& RHSKey) const
{
CKey RetKey;
//iterate through the keys
//the 0ht is the most important key
for (int i = 0; i < KEY_SIZE; i++)
RetKey.key[i] = key[i] - RHSKey.key[i];
return RetKey;
}
bool operator >(CKey& RHSKey)
{
//iterate through the keys
//the 0ht is the most important key
#if KEY_SIZE == 1
return (key[0] > RHSKey.key[0]);
#elif KEY_SIZE == 2
return (key[0] > RHSKey.key[0] || (key[0] == RHSKey.key[0] && key[1] > RHSKey.key[1]));
#else
for(int i = 0; i < KEY_SIZE; i++)
{
//compare the current key
if(key[i] > RHSKey.key[i])
return true;
else if(key[i] < RHSKey.key[i])
return false;
}
//all are equal
return false;
#endif
}
bool operator ==(CKey& RHSKey)
{
//iterate through the keys
//the 0ht is the most important key
#if KEY_SIZE == 1
return (key[0] == RHSKey.key[0]);
#elif KEY_SIZE == 2
return (key[0] == RHSKey.key[0] && key[1] == RHSKey.key[1]);
#else
for(int i = 0; i < KEY_SIZE; i++)
{
//compare the current key
if(key[i] != RHSKey.key[i])
return false;
}
//all are equal
return true;
#endif
}
bool operator !=(CKey& RHSKey)
{
return !(*this == RHSKey);
}
bool operator <(CKey& RHSKey)
{
//iterate through the keys
//the 0ht is the most important key
#if KEY_SIZE == 1
return (key[0] < RHSKey.key[0]);
#elif KEY_SIZE == 2
return (key[0] < RHSKey.key[0] || (key[0] == RHSKey.key[0] && key[1] < RHSKey.key[1]));
#else
for(int i = 0; i < KEY_SIZE; i++)
{
//compare the current key
if(key[i] < RHSKey.key[i])
return true;
else if(key[i] > RHSKey.key[i])
return false;
}
//all are equal
return false;
#endif
}
bool operator >=(CKey& RHSKey) { return !(*this < RHSKey); }
bool operator <=(CKey& RHSKey) { return !(*this > RHSKey); }
long int operator [](int i) { return key[i]; }
};
#endif

View File

@@ -0,0 +1,682 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LIST_H_
#define __LIST_H_
#include <cstdlib>
#include <sstream>
#include <sbpl/config.h>
#include <sbpl/sbpl_exception.h>
//the maximum size of the heap
#define LISTSIZE 5000000
struct listelement
{
AbstractSearchState *liststate;
struct listelement *prev;
struct listelement *next;
};
typedef struct listelement listelement;
class CList
{
//data
public:
listelement* firstelement;
listelement* lastelement;
int currentsize;
//constructors
public:
CList()
{
firstelement = NULL;
lastelement = NULL;
currentsize = 0;
}
~CList()
{
}
//functions
public:
bool empty() { return (currentsize == 0); }
bool full() { return (currentsize >= LISTSIZE); }
bool in(AbstractSearchState *AbstractSearchState1, int listindex)
{
return (AbstractSearchState1->listelem[listindex] != NULL);
}
void makeemptylist(int listindex)
{
while (firstelement != NULL)
remove(firstelement->liststate, listindex);
}
void insert(AbstractSearchState *AbstractSearchState1, int listindex)
{
if (currentsize >= LISTSIZE) {
throw SBPL_Exception("ERROR: list is full");
}
if (AbstractSearchState1->listelem[listindex] != NULL) {
throw SBPL_Exception("ERROR: insert: element is already in the list");
}
listelement *insertelem = (listelement*)malloc(sizeof(listelement));
insertelem->liststate = AbstractSearchState1;
insertelem->prev = NULL;
insertelem->next = firstelement;
if (firstelement != NULL) firstelement->prev = insertelem;
firstelement = insertelem;
if (lastelement == NULL) //if this is the first element to be inserted into the list
lastelement = insertelem;
AbstractSearchState1->listelem[listindex] = insertelem;
currentsize++;
}
void insertinfront(AbstractSearchState *AbstractSearchState1, int listindex)
{
insert(AbstractSearchState1, listindex);
}
void remove(AbstractSearchState *AbstractSearchState1, int listindex)
{
if (currentsize == 0 || AbstractSearchState1->listelem[listindex] == NULL) {
throw SBPL_Exception("ERROR: delete: list does not contain the element");
}
if (AbstractSearchState1->listelem[listindex]->prev != NULL && AbstractSearchState1->listelem[listindex]->next
!= NULL) {
//in the middle of the list
AbstractSearchState1->listelem[listindex]->prev->next = AbstractSearchState1->listelem[listindex]->next;
AbstractSearchState1->listelem[listindex]->next->prev = AbstractSearchState1->listelem[listindex]->prev;
}
else if (AbstractSearchState1->listelem[listindex]->prev != NULL) {
//at the end of the list
AbstractSearchState1->listelem[listindex]->prev->next = NULL;
lastelement = AbstractSearchState1->listelem[listindex]->prev;
}
else if (AbstractSearchState1->listelem[listindex]->next != NULL) {
//at the beginning of the list
AbstractSearchState1->listelem[listindex]->next->prev = NULL;
firstelement = AbstractSearchState1->listelem[listindex]->next;
}
else {
//the only element in the list
firstelement = NULL;
lastelement = NULL;
}
//delete
free(AbstractSearchState1->listelem[listindex]);
AbstractSearchState1->listelem[listindex] = NULL;
currentsize--;
}
AbstractSearchState *getfirst()
{
if (firstelement == NULL)
return NULL;
else
return firstelement->liststate;
}
AbstractSearchState *getlast()
{
if (lastelement == NULL)
return NULL;
else
return lastelement->liststate;
}
AbstractSearchState *getnext(AbstractSearchState* AbstractSearchState1, int listindex)
{
if (AbstractSearchState1->listelem[listindex]->next == NULL)
return NULL;
else
return AbstractSearchState1->listelem[listindex]->next->liststate;
}
};
class CBucket
{
//data
public:
//buckets are from first_priority to numofbuckets-3. Bucket numofbucket-2
//contains elements with higher finite priorities (unordered). Last bucket
//contains infinite priority elements
std::vector<AbstractSearchState *>* bucketV;
//contains the priorities of elements in the numofbuckets-2 bucket (mixed priorities)
std::vector<int> assortedpriorityV;
int firstpriority;
int numofbuckets;
int currentminelement_bucketind;
int currentminelement_priority;
int currentminelement_bucketVind; //index within the bucket
int maxassortedpriorityVsize;
//constructors
public:
CBucket(int first_priority, int max_bucketed_priority)
{
bucketV = NULL;
firstpriority = 0;
numofbuckets = 0;
currentminelement_bucketind = INFINITECOST;
currentminelement_priority = INFINITECOST;
currentminelement_bucketVind = INFINITECOST;
maxassortedpriorityVsize = 0;
reset(first_priority, max_bucketed_priority);
}
~CBucket()
{
if (bucketV != NULL) {
makeemptybucketV();
delete[] bucketV;
bucketV = NULL;
firstpriority = 0;
numofbuckets = 0;
}
}
//functions
public:
bool empty()
{
return (currentminelement_bucketind == INFINITECOST);
}
bool reset(int first_priority, int max_bucketed_priority)
{
//delete the old ones
if (numofbuckets != 0) {
makeemptybucketV();
delete[] bucketV;
bucketV = NULL;
firstpriority = 0;
numofbuckets = 0;
}
//compute the number of buckets
numofbuckets = max_bucketed_priority - first_priority + 1; //this is how many priorities are one per buckets
numofbuckets += 2; //one bucket for (max_bucketed_priority; infinity) and one bucket for infinity
//allocate memory
bucketV = new std::vector<AbstractSearchState *> [numofbuckets];
//currently all empty
currentminelement_bucketind = INFINITECOST;
currentminelement_priority = INFINITECOST;
currentminelement_bucketVind = INFINITECOST;
//reset statistics
maxassortedpriorityVsize = 0;
return true;
}
void makeemptybucketV()
{
for (int i = 0; i < numofbuckets; i++) {
for (int eind = 0; eind < (int)bucketV[i].size(); eind++) {
bucketV[i].at(eind)->heapindex = -1;
}
}
assortedpriorityV.clear(); //clear the assorted priorities array
//currently all empty
currentminelement_bucketind = INFINITECOST;
currentminelement_priority = INFINITECOST;
currentminelement_bucketVind = INFINITECOST;
}
AbstractSearchState *getminelement()
{
if (currentminelement_bucketind == INFINITECOST)
return NULL;
#if DEBUG
else if(currentminelement_bucketind >= numofbuckets)
{
throw SBPL_Exception("ERROR: currentminelement_bucketind is invalid");
}
else if((int)bucketV[currentminelement_bucketind].size() <= currentminelement_bucketVind)
{
throw SBPL_Exception("ERROR: failed to get minelement");
}
#endif
else {
return bucketV[currentminelement_bucketind].at(currentminelement_bucketVind);
}
}
AbstractSearchState *popminelement()
{
if (currentminelement_bucketind == INFINITECOST)
return NULL;
#if DEBUG
else if(currentminelement_bucketind >= numofbuckets)
{
throw SBPL_Exception("ERROR: currentminelement_bucketind is invalid");
}
else if((int)bucketV[currentminelement_bucketind].size() <= currentminelement_bucketVind)
{
throw SBPL_Exception("ERROR: failed to get minelement");
}
#endif
else {
AbstractSearchState* AbstractSearchState1 =
bucketV[currentminelement_bucketind].at(currentminelement_bucketVind);
removestategivenbucketindex(AbstractSearchState1, currentminelement_bucketind);
return AbstractSearchState1;
}
}
int getminpriority()
{
return currentminelement_priority;
}
void remove(AbstractSearchState *AbstractSearchState1, int priorityattimeofinsertion)
{
//compute bucketindex
int bucketindex = priorityattimeofinsertion - firstpriority;
if (priorityattimeofinsertion == INFINITECOST)
bucketindex = numofbuckets - 1;
else if (bucketindex > numofbuckets - 2) bucketindex = numofbuckets - 2;
removestategivenbucketindex(AbstractSearchState1, bucketindex);
}
void insert(AbstractSearchState *AbstractSearchState1, int priority)
{
//compute bucket index
int bucketindex = priority - firstpriority;
if (priority == INFINITECOST) {
bucketindex = numofbuckets - 1;
}
else if (bucketindex >= numofbuckets - 2) {
bucketindex = numofbuckets - 2; //overflow bucket
}
//insert the element itself
bucketV[bucketindex].push_back(AbstractSearchState1);
AbstractSearchState1->heapindex = (int)bucketV[bucketindex].size() - 1;
if (bucketindex == numofbuckets - 2) {
assortedpriorityV.push_back(priority);
if (maxassortedpriorityVsize < (int)assortedpriorityV.size()) maxassortedpriorityVsize
= (int)assortedpriorityV.size();
}
//re-compute minelement if necessary
if (priority < currentminelement_priority || currentminelement_priority == INFINITECOST) {
recomputeminelementupfrombucket(bucketindex);
}
}
private:
void removestategivenbucketindex(AbstractSearchState *AbstractSearchState1, int bucketindex)
{
int removeelemind = AbstractSearchState1->heapindex;
int lastelemind = (int)bucketV[bucketindex].size() - 1;
//put into its place the last element in the bucket
if (bucketindex == numofbuckets - 2) assortedpriorityV.at(removeelemind) = assortedpriorityV.at(lastelemind);
bucketV[bucketindex].at(lastelemind)->heapindex = removeelemind;
bucketV[bucketindex].at(removeelemind) = bucketV[bucketindex].at(lastelemind);
//clear the element itself
AbstractSearchState1->heapindex = -1;
//remove the last element
bucketV[bucketindex].pop_back();
//re-compute minelement if necessary
if (bucketindex == currentminelement_bucketind && ((int)bucketV[bucketindex].size() == 0 ||
currentminelement_bucketind == numofbuckets - 2))
{
recomputeminelementupfrombucket(bucketindex);
}
}
void recomputeminelementupfrombucket(int startbucketindex)
{
//first find non-empty bucket
int bind = -1;
for (bind = startbucketindex; bind < numofbuckets; bind++) {
if ((int)bucketV[bind].size() != 0) break;
}
if (bind < numofbuckets - 2) {
//normal bucket
currentminelement_bucketind = bind;
currentminelement_priority = firstpriority + bind;
currentminelement_bucketVind = 0;
}
else if (bind == (numofbuckets - 2)) {
//assorted priorities
currentminelement_bucketind = bind;
currentminelement_priority = INFINITECOST;
currentminelement_bucketVind = INFINITECOST;
for (int eind = 0; eind < (int)bucketV[bind].size(); eind++) {
if (currentminelement_priority > assortedpriorityV.at(eind)) {
currentminelement_priority = assortedpriorityV.at(eind);
currentminelement_bucketVind = eind;
}
}
if (currentminelement_priority == INFINITECOST) {
throw SBPL_Exception("ERROR: in recomputemin in buckets");
}
}
else if (bind == (numofbuckets - 1)) {
//bucket with infinite priorities
currentminelement_bucketind = bind;
currentminelement_priority = INFINITECOST;
currentminelement_bucketVind = 0;
}
else {
currentminelement_bucketind = INFINITECOST;
currentminelement_priority = INFINITECOST;
currentminelement_bucketVind = INFINITECOST;
}
}
};
class CSlidingBucket
{
//data
public:
//fixed size buckets. Each bucket is of size bucketsize, and there are numofbuckets buckets.
//all unoccupied buckets are supposed to be set to NULL
AbstractSearchState*** bucketV;
int* lastelementindexV; //index of the last element for each bucket
int numofbuckets;
int bucketsize;
int currentminelement_bindex; //index of the bucket of the current min element
int currentminelement_index; //index of the current minelement in the bucket
int currentmaxelement_priority; //the maxelement priority in the list
int currentminelement_priority; //the priority of the current minelement
int currentfirstbucket_bindex; //index of the bucket that corresponds to the first bucket in the list (lowest priority)
int currentfirstbucket_priority; //priority of the first bucket in the list
int* dynamicsize; //the size of bucket
int initialdynamicsize; //initial size of dynamic sized buckets or 0 for fixed size buckets
//constructors
public:
// an initial_dynamic_size of 0 will use fixed size buckets
CSlidingBucket(int num_of_buckets, int bucket_size, int initial_dynamic_size=0)
{
numofbuckets = num_of_buckets;
bucketsize = bucket_size;
initialdynamicsize = std::max(0, initial_dynamic_size);
//allocate memory
bucketV = new AbstractSearchState**[numofbuckets];
lastelementindexV = new int[numofbuckets];
if(initialdynamicsize)
{
dynamicsize = new int[numofbuckets];
for (int i = 0; i < numofbuckets; i++) {
dynamicsize[i] = 0;
}
}
for (int i = 0; i < numofbuckets; i++) {
lastelementindexV[i] = -1;
bucketV[i] = NULL;
}
currentminelement_bindex = currentfirstbucket_bindex = 0;
currentminelement_index = -1;
currentmaxelement_priority = currentminelement_priority = currentfirstbucket_priority = 0;
}
~CSlidingBucket()
{
for (int i = 0; i < numofbuckets; i++) {
if (bucketV[i] != NULL) {
if(initialdynamicsize)
free(bucketV[i]);
else
delete[] bucketV[i];
bucketV[i] = NULL;
}
}
if(initialdynamicsize)
delete [] dynamicsize;
delete[] bucketV;
bucketV = NULL;
delete[] lastelementindexV;
}
//functions
public:
inline bool empty()
{
return (currentminelement_index == -1 && currentmaxelement_priority == currentminelement_priority);
}
inline int getminkey()
{
return currentminelement_priority;
}
void reset()
{
currentminelement_bindex = currentfirstbucket_bindex = 0;
currentminelement_index = -1;
currentmaxelement_priority = currentminelement_priority = currentfirstbucket_priority = 0;
for (int i = 0; i < numofbuckets; i++) {
lastelementindexV[i] = -1;
if (bucketV[i] == NULL) continue;
if(initialdynamicsize)
{
for (int eind = 0; eind < dynamicsize[i]; eind++)
bucketV[i][eind] = NULL;
}
else
{
for (int eind = 0; eind < bucketsize; eind++)
bucketV[i][eind] = NULL;
}
}
}
AbstractSearchState *popminelement()
{
if (currentminelement_index == -1 && currentmaxelement_priority == currentminelement_priority)
return NULL;
else {
AbstractSearchState* currentelement = NULL;
if (currentminelement_index == -1 || bucketV[currentminelement_bindex] == NULL
|| bucketV[currentminelement_bindex][currentminelement_index] == NULL)
currentelement = recomputeandreturnmin();
else
currentelement = bucketV[currentminelement_bindex][currentminelement_index];
//delete the element
bucketV[currentminelement_bindex][currentminelement_index] = NULL;
//reset the first bucket to the element that was just delete
currentfirstbucket_bindex = currentminelement_bindex;
currentfirstbucket_priority = currentminelement_priority;
//recomputemin
recomputeandreturnmin();
return currentelement;
}
}
AbstractSearchState *getminelement()
{
if (currentminelement_index == -1 && currentmaxelement_priority == currentminelement_priority)
return NULL;
else {
AbstractSearchState* currentelement = NULL;
if (currentminelement_index == -1 || bucketV[currentminelement_bindex] == NULL
|| bucketV[currentminelement_bindex][currentminelement_index] == NULL)
currentelement = recomputeandreturnmin();
else
currentelement = bucketV[currentminelement_bindex][currentminelement_index];
return currentelement;
}
}
void insert(AbstractSearchState *AbstractSearchState1, int priority)
{
//compute the index of the bucket where to put it in
int bucket_increment = (priority - currentfirstbucket_priority);
int bucket_index = (currentfirstbucket_bindex + bucket_increment) % numofbuckets;
if (bucket_increment >= numofbuckets || bucket_increment < 0) {
std::stringstream ss;
ss << "ERROR: invalid priority=" << priority <<
" (currentfirstbucket_priority=" <<
currentfirstbucket_priority <<
") used with sliding buckets";
throw SBPL_Exception(ss.str());
}
//insert the element
lastelementindexV[bucket_index]++;
if (lastelementindexV[bucket_index] == bucketsize) {
std::stringstream ss;
ss << "ERROR: bucket " << bucket_index << " is full (size=" << bucketsize << ")";
throw SBPL_Exception(ss.str());
}
if (bucketV[bucket_index] == NULL) createbucket(bucket_index);
if(initialdynamicsize)
{
// resize the bucket if needed
if(lastelementindexV[bucket_index] >= dynamicsize[bucket_index])
{
const int new_size = std::min(dynamicsize[bucket_index]*2, bucketsize);
if(new_size != dynamicsize[bucket_index])
{
bucketV[bucket_index] = (AbstractSearchState**) realloc(bucketV[bucket_index], sizeof(AbstractSearchState*) * new_size);
for(int i=dynamicsize[bucket_index]; i<new_size; i++)
{
bucketV[bucket_index][i] = NULL;
}
dynamicsize[bucket_index] = new_size;
}
}
}
bucketV[bucket_index][lastelementindexV[bucket_index]] = AbstractSearchState1;
//make sure maximum and minimum is correct
if (priority > currentmaxelement_priority) currentmaxelement_priority = priority;
if (priority < currentminelement_priority) {
currentminelement_priority = priority;
currentminelement_bindex = bucket_index;
}
//special case for the only entry
if (currentminelement_bindex == bucket_index && currentminelement_index == -1) {
currentminelement_index = 0;
}
}
private:
AbstractSearchState *recomputeandreturnmin()
{
if (currentminelement_index == -1 && currentmaxelement_priority == currentminelement_priority) return NULL;
while (currentminelement_index == -1 || bucketV[currentminelement_bindex] == NULL ||
bucketV[currentminelement_bindex][currentminelement_index] == NULL)
{
//try incrementing element index
if (currentminelement_index < lastelementindexV[currentminelement_bindex])
currentminelement_index++;
else {
//there are no more elements left in this bucket
lastelementindexV[currentminelement_bindex] = -1;
//if it was the last bucket, then that is it
if (currentminelement_priority == currentmaxelement_priority) {
currentminelement_index = -1;
currentmaxelement_priority = currentminelement_priority;
return NULL;
}
//try incrementing bucket index
currentminelement_bindex = (currentminelement_bindex + 1) % numofbuckets;
currentminelement_index = 0;
currentminelement_priority++;
}
}
return bucketV[currentminelement_bindex][currentminelement_index];
}
void createbucket(int bucketindex)
{
if (bucketV[bucketindex] != NULL) {
throw SBPL_Exception("ERROR: trying to create a non-null bucket");
}
if(initialdynamicsize)
{
dynamicsize[bucketindex] = initialdynamicsize;
bucketV[bucketindex] = (AbstractSearchState**) malloc(sizeof(AbstractSearchState*) * dynamicsize[bucketindex] );
for (int eind = 0; eind < dynamicsize[bucketindex]; eind++)
bucketV[bucketindex][eind] = NULL;
}
else
{
bucketV[bucketindex] = new AbstractSearchState*[bucketsize];
for (int eind = 0; eind < bucketsize; eind++)
bucketV[bucketindex][eind] = NULL;
}
}
};
#endif

View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __MDP_H_
#define __MDP_H_
#include <cstdio>
#include <vector>
#include <sbpl/config.h>
#include <sbpl/sbpl_exception.h>
#define EPS_ERROR 0.000001
//the maximum size of the heap
#define MAXSTATESPACESIZE 20000000
class CMDPSTATE;
class CMDPACTION
{
public:
//data
int ActionID;
int SourceStateID;
std::vector<int> SuccsID;
std::vector<int> Costs;
std::vector<float> SuccsProb;
void* PlannerSpecificData;
//constructors
CMDPACTION(int ID, int sourcestateid)
{
ActionID = ID;
SourceStateID = sourcestateid;
PlannerSpecificData = NULL;
}
~CMDPACTION()
{
if (PlannerSpecificData != NULL) {
const char* msg = "ERROR: state deletion: planner specific data is not deleted";
SBPL_FPRINTF(stderr, "%s\n", msg);
throw SBPL_Exception(msg);
}
}
//functions
bool Delete();
bool IsValid();
void AddOutcome(int OutcomeStateID, int OutcomeCost, float OutcomeProb);
int GetIndofMostLikelyOutcome();
int GetIndofOutcome(int OutcomeID);
bool DeleteAllOutcomes();
//operators
void operator =(const CMDPACTION& rhsaction);
};
class CMDPSTATE
{
public:
//data
int StateID;
std::vector<CMDPACTION*> Actions;
std::vector<int> PredsID;
void* PlannerSpecificData;
//constructors
CMDPSTATE(int ID)
{
StateID = ID;
PlannerSpecificData = NULL;
}
~CMDPSTATE()
{
if (PlannerSpecificData != NULL) {
const char* msg = "ERROR: state deletion: planner specific data is not deleted";
SBPL_FPRINTF(stderr, "%s\n", msg);
throw SBPL_Exception(msg);
}
}
//functions
bool Delete();
CMDPACTION* AddAction(int ID);
bool ContainsPred(int stateID);
bool AddPred(int stateID);
bool RemovePred(int stateID);
bool RemoveAllActions();
CMDPACTION* GetAction(int actionID);
//operators
void operator =(const CMDPSTATE& rhsstate);
};
class CMDP
{
public:
//data
std::vector<CMDPSTATE*> StateArray;
//constructors
CMDP() { }
~CMDP() { }
//functions
bool empty();
bool full();
//creates numofstates states. Their ids are their orderings for Original, Thresholded & Search MDPs
bool Create(int numofstates);
bool Delete();
void Print(FILE* fOut);
CMDPSTATE* AddState(int StateID);
};
#endif

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __MDPCONFIG_H_
#define __MDPCONFIG_H_
struct MDPConfig
{
int startstateid;
int goalstateid;
};
#endif

View File

@@ -0,0 +1,221 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SBPL_BFS_2D
#define SBPL_BFS_2D
#include <vector>
#include <sbpl/utils/sbpl_fifo.h>
class sbpl_bfs_2d
{
private:
class bfs_cell_2d
{
public:
bfs_cell_2d()
{
x = 0;
y = 0;
}
bfs_cell_2d(int tempX, int tempY)
{
x = tempX;
y = tempY;
}
int x;
int y;
};
public:
sbpl_bfs_2d(unsigned int sx, unsigned int sy, int obs_thresh, int fifo_size = -1) :
NUM_ACTIONS(8)
{
size_x_ = sx;
size_y_ = sy;
thresh_ = obs_thresh;
//initialize the fifo
if (fifo_size < 0) fifo_size = 2 * sx + 2 * sy;
q_ = new sbpl_fifo<bfs_cell_2d> (fifo_size);
//initialize the distance grid
dist_ = new int*[size_x_];
for (int x = 0; x < size_x_; x++)
dist_[x] = new int[size_y_];
//initialize the actions
dx = new int[NUM_ACTIONS];
dy = new int[NUM_ACTIONS];
int idx = 0;
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
if (!x && !y) continue;
dx[idx] = x;
dy[idx] = y;
idx++;
}
}
}
~sbpl_bfs_2d()
{
//delete the fifo
delete q_;
//delete the distance grid
for (int x = 0; x < size_x_; x++)
delete[] dist_[x];
delete[] dist_;
//delete the actions
delete[] dx;
delete[] dy;
}
bool compute_distance_from_point(int** grid, int x, int y)
{
if (x < 0 || x >= size_x_ || y < 0 || y >= size_y_) {
printf("ERROR[compute_distance_from_point]: point is out of bounds!\n");
return false;
}
q_->clear();
clear_distances();
bfs_cell_2d c(x, y);
q_->insert(c);
dist_[x][y] = 0;
compute_distances(grid);
return true;
}
bool compute_distance_from_points(int** grid, std::vector<int> x, std::vector<int> y)
{
if (x.size() != y.size()) {
printf("ERROR[compute_distance_from_points]: size of x and y coordinates must agree!\n");
return false;
}
q_->clear();
clear_distances();
for (unsigned int i = 0; i < x.size(); i++) {
if (x[i] < 0 || x[i] >= size_x_ || y[i] < 0 || y[i] >= size_y_) {
printf("ERROR[compute_distance_from_points]: point is out of bounds!\n");
return false;
}
bfs_cell_2d c(x[i], y[i]);
q_->insert(c);
dist_[x[i]][y[i]] = 0;
}
compute_distances(grid);
return true;
}
void compute_distance_from_obs(int** grid)
{
q_->clear();
clear_distances();
for (int x = 0; x < size_x_; x++) {
for (int y = 0; y < size_y_; y++) {
if (grid[x][y] >= thresh_) {
bfs_cell_2d c(x, y);
q_->insert(c);
dist_[x][y] = 0;
}
}
}
compute_distances(grid);
}
void clear_distances()
{
for (int x = 0; x < size_x_; x++)
for (int y = 0; y < size_y_; y++)
dist_[x][y] = -1;
}
void compute_distances(int** grid)
{
bfs_cell_2d c;
while (!q_->empty()) {
q_->remove(&c);
int cost = dist_[c.x][c.y] + 1;
if (c.x == 0 || c.x == size_x_ - 1 || c.y == 0 || c.y == size_y_ - 1) {
//we are on a boundary so we have to bounds check each successor
for (int i = 0; i < NUM_ACTIONS; i++) {
int x = c.x + dx[i];
int y = c.y + dy[i];
if (x < 0 || x >= size_x_ || y < 0 || y >= size_y_) continue;
if (dist_[x][y] < 0 && grid[x][y] < thresh_) {
dist_[x][y] = cost;
bfs_cell_2d temp(x, y);
q_->insert(temp);
}
}
}
else {
//we are not near a boundary so no bounds check is required
for (int i = 0; i < NUM_ACTIONS; i++) {
int x = c.x + dx[i];
int y = c.y + dy[i];
if (dist_[x][y] < 0 && grid[x][y] < thresh_) {
dist_[x][y] = cost;
bfs_cell_2d temp(x, y);
q_->insert(temp);
}
}
}
}
}
int get_distance(unsigned int x, unsigned int y)
{
return dist_[x][y];
}
private:
int** dist_;
sbpl_fifo<bfs_cell_2d>* q_;
int size_x_;
int size_y_;
int thresh_;
const int NUM_ACTIONS;
int* dx;
int* dy;
};
#endif

View File

@@ -0,0 +1,242 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SBPL_BFS_3D
#define SBPL_BFS_3D
#include <vector>
#include <sbpl/utils/sbpl_fifo.h>
class sbpl_bfs_3d
{
private:
class bfs_cell_3d
{
public:
bfs_cell_3d()
{
x = 0;
y = 0;
z = 0;
}
bfs_cell_3d(int tempX, int tempY, int tempZ)
{
x = tempX;
y = tempY;
z = tempZ;
}
;
int x;
int y;
int z;
};
public:
sbpl_bfs_3d(unsigned int sx, unsigned int sy, unsigned int sz, int obs_thresh, int fifo_size = -1) :
NUM_ACTIONS(26)
{
size_x_ = sx;
size_y_ = sy;
size_z_ = sz;
thresh_ = obs_thresh;
//initialize the fifo
if (fifo_size < 0) fifo_size = 2 * sx * sy + 2 * sx * sz + 2 * sy * sz;
q_ = new sbpl_fifo<bfs_cell_3d> (fifo_size);
//initialize the distance grid
dist_ = new int**[size_x_];
for (int x = 0; x < size_x_; x++) {
dist_[x] = new int*[size_y_];
for (int y = 0; y < size_y_; y++)
dist_[x][y] = new int[size_z_];
}
//initialize the actions
dx = new int[NUM_ACTIONS];
dy = new int[NUM_ACTIONS];
dz = new int[NUM_ACTIONS];
int idx = 0;
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
for (int z = -1; z <= 1; z++) {
if (!x && !y && !z) continue;
dx[idx] = x;
dy[idx] = y;
dz[idx] = z;
idx++;
}
}
}
}
~sbpl_bfs_3d()
{
//delete the fifo
delete q_;
//delete the distance grid
for (int x = 0; x < size_x_; x++) {
for (int y = 0; y < size_y_; y++)
delete[] dist_[x][y];
delete[] dist_[x];
}
delete[] dist_;
//delete the actions
delete[] dx;
delete[] dy;
delete[] dz;
}
bool compute_distance_from_point(int*** grid, int x, int y, int z)
{
if (x < 0 || x >= size_x_ || y < 0 || y >= size_y_ || z < 0 || z >= size_z_) {
printf("ERROR[compute_distance_from_point]: point is out of bounds!\n");
return false;
}
q_->clear();
clear_distances();
bfs_cell_3d c(x, y, z);
q_->insert(c);
dist_[x][y][z] = 0;
compute_distances(grid);
return true;
}
bool compute_distance_from_points(int*** grid, std::vector<int> x, std::vector<int> y, std::vector<int> z)
{
if (x.size() != y.size() || x.size() != z.size()) {
printf("ERROR[compute_distance_from_points]: size of x, y, and z coordinates must agree!\n");
return false;
}
q_->clear();
clear_distances();
for (unsigned int i = 0; i < x.size(); i++) {
if (x[i] < 0 || x[i] >= size_x_ || y[i] < 0 || y[i] >= size_y_ || z[i] < 0 || z[i] >= size_z_) {
printf("ERROR[compute_distance_from_points]: point is out of bounds!\n");
return false;
}
bfs_cell_3d c(x[i], y[i], z[i]);
q_->insert(c);
dist_[x[i]][y[i]][z[i]] = 0;
}
compute_distances(grid);
return true;
}
void compute_distance_from_obs(int*** grid)
{
q_->clear();
clear_distances();
for (int x = 0; x < size_x_; x++) {
for (int y = 0; y < size_y_; y++) {
for (int z = 0; z < size_z_; z++) {
if (grid[x][y][z] >= thresh_) {
bfs_cell_3d c(x, y, z);
q_->insert(c);
dist_[x][y][z] = 0;
}
}
}
}
compute_distances(grid);
}
void clear_distances()
{
for (int x = 0; x < size_x_; x++)
for (int y = 0; y < size_y_; y++)
for (int z = 0; z < size_z_; z++)
dist_[x][y][z] = -1;
}
void compute_distances(int*** grid)
{
bfs_cell_3d c;
while (!q_->empty()) {
q_->remove(&c);
int cost = dist_[c.x][c.y][c.z] + 1;
if (c.x == 0 || c.x == size_x_ - 1 || c.y == 0 || c.y == size_y_ - 1 || c.z == 0 || c.z == size_z_ - 1) {
//we are on a boundary so we have to bounds check each successor
for (int i = 0; i < NUM_ACTIONS; i++) {
int x = c.x + dx[i];
int y = c.y + dy[i];
int z = c.z + dz[i];
if (x < 0 || x >= size_x_ || y < 0 || y >= size_y_ || z < 0 || z >= size_z_) continue;
if (dist_[x][y][z] < 0 && grid[x][y][z] < thresh_) {
dist_[x][y][z] = cost;
bfs_cell_3d temp(x, y, z);
q_->insert(temp);
}
}
}
else {
//we are not near a boundary so no bounds check is required
for (int i = 0; i < NUM_ACTIONS; i++) {
int x = c.x + dx[i];
int y = c.y + dy[i];
int z = c.z + dz[i];
if (dist_[x][y][z] < 0 && grid[x][y][z] < thresh_) {
dist_[x][y][z] = cost;
bfs_cell_3d temp(x, y, z);
q_->insert(temp);
}
}
}
}
}
int get_distance(unsigned int x, unsigned int y, unsigned int z)
{
return dist_[x][y][z];
}
private:
int*** dist_;
sbpl_fifo<bfs_cell_3d>* q_;
int size_x_;
int size_y_;
int size_z_;
int thresh_;
const int NUM_ACTIONS;
int* dx;
int* dy;
int* dz;
};
#endif

View File

@@ -0,0 +1,95 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SBPL_FIFO
#define SBPL_FIFO
#include <cstdio>
template<class T>
class sbpl_fifo
{
public:
sbpl_fifo(unsigned int size)
{
q_ = new T[size];
head_ = 0;
tail_ = 0;
size_ = size;
}
~sbpl_fifo()
{
delete[] q_;
}
bool insert(T val)
{
int t_val = tail_;
if (t_val == head_ + 1 || (t_val == 0 && head_ + 1 == size_)) {
printf("ERROR: Trying to insert when FIFO is full!\n");
return false;
}
q_[head_] = val;
head_++;
if (head_ == size_) head_ = 0;
return true;
}
bool remove(T* val)
{
if (head_ == tail_) {
printf("ERROR: Trying to remove when FIFO is empty!\n");
return false;
}
*val = q_[tail_];
tail_++;
if (tail_ == size_) tail_ = 0;
return true;
}
bool empty()
{
return head_ == tail_;
}
void clear()
{
head_ = 0;
tail_ = 0;
}
private:
int head_;
int tail_;
int size_;
T* q_;
};
#endif

View File

@@ -0,0 +1,303 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __UTILS_H_
#define __UTILS_H_
#include <cstdio>
#include <set>
#include <vector>
#ifndef WIN32
#define __max(x,y) (x>y?x:y)
#define __min(x,y) (x>y?y:x)
#endif
#define nav2dcell_t sbpl_2Dcell_t
#define EnvNAVXYTHETALAT2Dpt_t sbpl_2Dcell_t
#define EnvNAVXYTHETALAT3Dpt_t sbpl_xy_theta_pt_t
#define EnvNAVXYTHETALAT3Dcell_t sbpl_xy_theta_cell_t
#define NORMALIZEDISCTHETA(THETA, THETADIRS) (((THETA >= 0) ?\
((THETA) % (THETADIRS)) :\
(((THETA) % (THETADIRS) + THETADIRS) % THETADIRS)))
#define CONTXY2DISC(X, CELLSIZE) (((X)>=0)?((int)((X)/(CELLSIZE))):((int)((X)/(CELLSIZE))-1))
#define DISCXY2CONT(X, CELLSIZE) ((X)*(CELLSIZE) + (CELLSIZE)/2.0)
#define PI_CONST 3.141592653589793238462643383279502884
#define UNKNOWN_COST 1000000
class CMDP;
class PlannerStats;
typedef struct
{
int X1, Y1;
int X2, Y2;
int Increment;
int UsingYIndex;
int DeltaX, DeltaY;
int DTerm;
int IncrE, IncrNE;
int XIndex, YIndex;
int Flipped;
} bresenham_param_t;
class sbpl_2Dcell_t
{
public:
sbpl_2Dcell_t()
{
x = 0;
y = 0;
}
sbpl_2Dcell_t(int x_, int y_)
{
x = x_;
y = y_;
}
bool operator==(const sbpl_2Dcell_t cell) const
{
return x == cell.x && y == cell.y;
}
bool operator<(const sbpl_2Dcell_t cell) const
{
return x < cell.x || (x == cell.x && y < cell.y);
}
int x;
int y;
};
class sbpl_2Dpt_t
{
public:
sbpl_2Dpt_t()
{
x = 0;
y = 0;
}
sbpl_2Dpt_t(double x_, double y_)
{
x = x_;
y = y_;
}
bool operator==(const sbpl_2Dpt_t p) const
{
return x == p.x && y == p.y;
}
bool operator<(const sbpl_2Dpt_t p) const
{
return x < p.x || (x == p.x && y < p.y);
}
double x;
double y;
};
class sbpl_xy_theta_cell_t
{
public:
sbpl_xy_theta_cell_t()
{
x = 0;
y = 0;
theta = 0;
}
sbpl_xy_theta_cell_t(int x_, int y_, int theta_)
{
x = x_;
y = y_;
theta = theta_;
}
bool operator==(const sbpl_xy_theta_cell_t cell) const
{
return x == cell.x && y == cell.y && theta == cell.theta;
}
bool operator<(const sbpl_xy_theta_cell_t cell) const
{
return x < cell.x || (x == cell.x && (y < cell.y || (y == cell.y && theta < cell.theta)));
}
int x;
int y;
int theta;
};
class sbpl_xy_theta_pt_t
{
public:
sbpl_xy_theta_pt_t()
{
x = 0;
y = 0;
theta = 0;
}
sbpl_xy_theta_pt_t(double x_, double y_, double theta_)
{
x = x_;
y = y_;
theta = theta_;
}
bool operator==(const sbpl_xy_theta_pt_t p) const
{
return x == p.x && y == p.y && theta == p.theta;
}
bool operator<(const sbpl_xy_theta_pt_t p) const
{
return x < p.x || (x == p.x && (y < p.y || (y == p.y && theta < p.theta)));
}
double x;
double y;
double theta;
};
typedef struct BINARYHIDDENVARIABLE
{
int h_ID; //ID of the variable
unsigned char Prob;
} sbpl_BinaryHiddenVar_t;
typedef struct BELIEFSTATEWITHBINARYHVALS
{
int s_ID; //ID of S part of state-space
//vector of updated h-values, the rest are the same as at the start state
std::vector<sbpl_BinaryHiddenVar_t> updatedhvaluesV;
} sbpl_BeliefStatewithBinaryh_t;
typedef struct POLICYBELIEFSTATEWITHBINARYHVALS
{
sbpl_BeliefStatewithBinaryh_t BeliefState; //current belief state
int nextpolicyactionID; //ID of the next policy action if exists (otherwise -1)
//indices of the outcome states of the policy action. If outcome state is not in the policy, then it is -1
std::vector<int> outcomestateIndexV;
} sbpl_PolicyStatewithBinaryh_t;
//function prototypes
#if MEM_CHECK == 1
void DisableMemCheck();
void EnableMemCheck();
#endif
void CheckMDP(CMDP* mdp);
void PrintMatrix(int** matrix, int rows, int cols, FILE* fOut);
void EvaluatePolicy(CMDP* PolicyMDP, int StartStateID, int GoalStateID, double* PolValue, bool* bFullPolicy,
double* Pcgoal, int* nMerges, bool* bCycles);
int ComputeNumofStochasticActions(CMDP* pMDP);
/**
* \brief one of the three functions that correspond to bresenham algorithm of
* path following this function computes bresenham parameters given the
* start and end points on the line segment
*/
void get_bresenham_parameters(int p1x, int p1y, int p2x, int p2y, bresenham_param_t* params);
/**
* \brief one of the three functions that correspond to bresenham algorithm of
* path following returns current cell on the line segment
*/
void get_current_point(bresenham_param_t* params, int* x, int* y);
/**
* \brief one of the three functions that correspond to bresenham algorithm of
* path following moves to the next point
*/
int get_next_point(bresenham_param_t* params);
/**
* \brief converts discretized version of angle into continuous (radians)
*
* \note maps 0->0, 1->delta, 2->2*delta, ...
*/
double DiscTheta2Cont(int nTheta, int NUMOFANGLEVALS);
/**
* \brief converts continuous (radians) version of angle into discrete
*
* \note maps 0->0, [delta/2, 3/2*delta)->1, [3/2*delta, 5/2*delta)->2,...
*/
int ContTheta2Disc(double fTheta, int NUMOFANGLEVALS);
/**
* \note counterclockwise is positive
* \param angle input angle should be in radians
* \return output is an angle in the range of from 0 to 2*PI
*/
double normalizeAngle(double angle);
/**
* \brief computes minimum unsigned difference between two angles in radians
*/
double computeMinUnsignedAngleDiff(double angle1, double angle2);
/**
* \brief returns true if 2D point is within the specified polygon given by
* ordered sequence of 2D points (last point is automatically connected to the
* first)
*/
bool IsInsideFootprint(sbpl_2Dpt_t pt, std::vector<sbpl_2Dpt_t>* bounding_polygon);
/**
* \brief computes 8-connected distances - performs distance transform in two linear passes
*/
void computeDistancestoNonfreeAreas(unsigned char** Grid2D, int width_x, int height_y, unsigned char obsthresh,
float** disttoObs_incells, float** disttoNonfree_incells);
void get_2d_motion_cells(std::vector<sbpl_2Dpt_t> polygon, std::vector<sbpl_xy_theta_pt_t> poses,
std::vector<sbpl_2Dcell_t>* cells, double res);
void get_2d_footprint_cells(std::vector<sbpl_2Dpt_t> polygon, std::vector<sbpl_2Dcell_t>* cells,
sbpl_xy_theta_pt_t pose, double res);
void get_2d_footprint_cells(std::vector<sbpl_2Dpt_t> polygon, std::set<sbpl_2Dcell_t>* cells, sbpl_xy_theta_pt_t pose,
double res);
void writePlannerStats(std::vector<PlannerStats> s, FILE* fout);
#if 0
void CheckSearchMDP(CMDP* mdp, int ExcludeSuccStateID = -1);
void CheckSearchPredSucc(CMDPSTATE* state, int ExcludeSuccStateID = -1);
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,671 @@
/*
* Copyright (c) 2013, Mike Phillips and Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sbpl/planners/lazyARA.h>
#include <sstream>
using namespace std;
LazyARAPlanner::LazyARAPlanner(
DiscreteSpaceInformation* environment,
bool bSearchForward)
:
params(0.0)
{
bforwardsearch = bSearchForward;
environment_ = environment;
replan_number = 0;
goal_state_id = -1;
start_state_id = -1;
}
LazyARAPlanner::~LazyARAPlanner()
{
freeMemory();
}
void LazyARAPlanner::freeMemory()
{
heap.makeemptyheap();
incons.clear();
stats.clear();
for (unsigned int i = 0; i < states.size(); i++) {
if (states[i]) {
delete states[i];
}
}
states.clear();
}
LazyARAState* LazyARAPlanner::GetState(int id)
{
// if this stateID is out of bounds of our state vector then grow the list
if (id >= int(states.size())) {
for (int i = states.size(); i <= id; i++) {
states.push_back(NULL);
}
}
// if we have never seen this state then create one
if (states[id] == NULL) {
states[id] = new LazyARAState();
states[id]->id = id;
states[id]->replan_number = -1;
}
// initialize the state if it hasn't been for this call to replan
LazyARAState* s = states[id];
if (s->replan_number != replan_number) {
s->g = INFINITECOST;
s->v = INFINITECOST;
s->iteration_closed = -1;
s->replan_number = replan_number;
s->best_parent = NULL;
s->expanded_best_parent = NULL;
s->heapindex = 0;
s->in_incons = false;
s->isTrueCost = true;
// clear the lazy list
while (!s->lazyList.empty()) {
s->lazyList.pop();
}
//compute heuristics
if (bforwardsearch) {
s->h = environment_->GetGoalHeuristic(s->id);
}
else {
s->h = environment_->GetStartHeuristic(s->id);
}
}
return s;
}
void LazyARAPlanner::ExpandState(LazyARAState* parent)
{
SBPL_DEBUG("expand %d", parent->id);
vector<int> children;
vector<int> costs;
vector<bool> isTrueCost;
if (bforwardsearch) {
environment_->GetLazySuccs(parent->id, &children, &costs, &isTrueCost);
}
else
environment_->GetLazyPreds(parent->id, &children, &costs, &isTrueCost);
// iterate through children of the parent
for (int i = 0; i < (int)children.size(); i++) {
LazyARAState* child = GetState(children[i]);
insertLazyList(child, parent, costs[i], isTrueCost[i]);
}
}
// assumptions:
// state is at the front of the open list
// it's minimum f-value is an underestimate (the edge cost from the parent is a guess and needs to be evaluated properly)
// it hasn't been expanded yet this iteration
void LazyARAPlanner::EvaluateState(LazyARAState* state)
{
SBPL_DEBUG("evaluate %d (from %d)", state->id, state->best_parent->id);
LazyARAState* parent = state->best_parent;
getNextLazyElement(state);
int trueCost;
if (bforwardsearch) {
trueCost = environment_->GetTrueCost(parent->id, state->id);
}
else {
trueCost = environment_->GetTrueCost(state->id, parent->id);
}
// if the evaluated true cost is valid (positive), insert it into the lazy list
if (trueCost > 0) {
SBPL_DEBUG(" edge is valid with cost %d added to parent->v=%d", trueCost, parent->v);
insertLazyList(state, parent, trueCost, true);
}
else{
SBPL_DEBUG(" edge not valid");
}
}
// this should only be used with EvaluateState since it is assuming state hasn't
// been expanded yet (only evaluated)
void LazyARAPlanner::getNextLazyElement(LazyARAState* state)
{
if (state->lazyList.empty()) {
state->g = INFINITECOST;
state->best_parent = NULL;
state->isTrueCost = true;
return;
}
LazyListElement elem = state->lazyList.top();
state->lazyList.pop();
state->g = elem.parent->v + elem.edgeCost;
state->best_parent = elem.parent;
state->isTrueCost = elem.isTrueCost;
// the new value is cheapest and if the value is also true then we want to
// throw out all the other options
if (state->isTrueCost) {
while (!state->lazyList.empty()) {
state->lazyList.pop();
}
}
putStateInHeap(state);
}
void LazyARAPlanner::insertLazyList(
LazyARAState* state,
LazyARAState* parent,
int edgeCost,
bool isTrueCost)
{
SBPL_DEBUG("insertLazyList state->id=%d parent->id=%d state->g=%d parent->v=%d edgeCost=%d isTrueCost=%d\n", state->id, parent->id, state->g, parent->v, edgeCost, isTrueCost);
if (state->v <= parent->v + edgeCost) {
return;
}
else if (state->g <= parent->v + edgeCost){
//if the best g-value we have is true and better, then the value we had dominates this one and we don't need it
if (state->isTrueCost) {
return;
}
//insert this guy into the lazy list
LazyListElement elem(parent, edgeCost, isTrueCost);
state->lazyList.push(elem);
}
else {
// the new guy is the cheapest so far
// should we save what was the previous best?
if (!isTrueCost && // the better guy's cost is not for sure
// state->g < INFINITECOST && // we actually have a previous best (we actually don't need this line because of the next one)
state->g < state->v) // we're not saving something we already expanded (and is stored in v and expanded_best_parent)
{
//we save it by putting it in the lazy list
LazyListElement elem(state->best_parent, state->g - state->best_parent->v, state->isTrueCost);
state->lazyList.push(elem);
}
// the new guy is the cheapest
state->g = parent->v + edgeCost;
state->best_parent = parent;
state->isTrueCost = isTrueCost;
// the new value is cheapest and if the value is also true then we want
// to throw out all the other options
if (isTrueCost) {
while (!state->lazyList.empty()) {
state->lazyList.pop();
}
}
// this function puts the state into the heap (or updates the position)
// if we haven't expanded. if we have expanded, it will put the state in
// the incons list (if we haven't already)
putStateInHeap(state);
}
}
void LazyARAPlanner::putStateInHeap(LazyARAState* state)
{
// we only allow one expansion per search iteration
// so insert into heap if not closed yet
if (state->iteration_closed != search_iteration) {
SBPL_DEBUG("put state %d in open with state->g=%d and state->isTrueCost=%d\n", state->id, state->g, state->isTrueCost);
CKey key;
key.key[0] = state->g + int(eps * state->h);
// if the state is already in the heap, just update its priority
if (state->heapindex != 0) {
heap.updateheap(state, key);
}
else { // otherwise add it to the heap
heap.insertheap(state, key);
}
}
// if the state has already been expanded once for this iteration then add
// it to the incons list so we can keep track of states that we know we have
// better costs for
else if (!state->in_incons) {
SBPL_DEBUG("put state %d in incons with state->g=%d and state->isTrueCost=%d\n", state->id, state->g, state->isTrueCost);
incons.push_back(state);
state->in_incons = true;
}
}
// returns 1 if the solution is found, 0 if the solution does not exist and 2 if
// it ran out of time
int LazyARAPlanner::ImprovePath()
{
// expand states until done
int expands = 0;
CKey min_key = heap.getminkeyheap();
while (!heap.emptyheap() &&
min_key.key[0] < INFINITECOST &&
(goal_state->g > min_key.key[0] || !goal_state->isTrueCost) &&
(goal_state->v > min_key.key[0]) &&
!outOfTime())
{
// get the state
LazyARAState* state = (LazyARAState*)heap.deleteminheap();
if (state->v == state->g) {
std::stringstream ss("ERROR: consistent state is being esxpanded ");
ss << "id=" << state->id;
ss << "v=" << state->v;
ss << "g=" << state->g;
ss << "isTrueCost=" << state->isTrueCost;
ss << "lazyListSize=" << state->lazyList.size();
throw SBPL_Exception(ss.str());
}
if (state->isTrueCost) {
// mark the state as expanded
state->v = state->g;
state->expanded_best_parent = state->best_parent;
state->iteration_closed = search_iteration;
// expand the state
expands++;
ExpandState(state);
if (expands % 100000 == 0) {
SBPL_DEBUG("expands so far=%u", expands);
}
}
else {
// otherwise the state needs to be evaluated for its true cost
EvaluateState(state);
}
// get the min key for the next iteration
min_key = heap.getminkeyheap();
}
search_expands += expands;
if (goal_state->v < goal_state->g) {
goal_state->g = goal_state->v;
goal_state->best_parent = goal_state->expanded_best_parent;
}
if (goal_state->g == INFINITECOST && (heap.emptyheap() || min_key.key[0] >= INFINITECOST)) {
return 0; // solution does not exists
}
if (!heap.emptyheap() && goal_state->g > min_key.key[0]) {
return 2; // search exited because it ran out of time
}
SBPL_DEBUG("search exited with a solution for eps=%.3f", eps);
if (goal_state->g < goal_state->v) {
goal_state->expanded_best_parent = goal_state->best_parent;
goal_state->v = goal_state->g;
}
return 1;
}
vector<int> LazyARAPlanner::GetSearchPath(int& solcost)
{
vector<int> SuccIDV;
vector<int> CostV;
vector<bool> isTrueCost;
vector<int> wholePathIds;
LazyARAState* state = goal_state;
LazyARAState* final_state = start_state;
// if the goal was not expanded but was generated (we don't have a bound on
// the solution) pretend that it was expanded for path reconstruction and
// revert the state afterward
bool goal_expanded = true;
if (goal_state->expanded_best_parent == NULL) {
goal_expanded = false;
goal_state->expanded_best_parent = goal_state->best_parent;
goal_state->v = goal_state->g;
}
wholePathIds.push_back(state->id);
solcost = 0;
while (state->id != final_state->id) {
if (state->expanded_best_parent == NULL) {
SBPL_DEBUG("a state along the path has no parent!");
break;
}
if (state->v == INFINITECOST) {
SBPL_DEBUG("a state along the path has an infinite g-value!");
SBPL_DEBUG("inf state = %d", state->id);
break;
}
if (bforwardsearch) {
environment_->GetLazySuccs(state->expanded_best_parent->id, &SuccIDV, &CostV, &isTrueCost);
}
else {
environment_->GetLazyPreds(state->expanded_best_parent->id, &SuccIDV, &CostV, &isTrueCost);
}
int actioncost = INFINITECOST;
for (unsigned int i = 0; i < SuccIDV.size(); i++) {
if (SuccIDV[i] == state->id && CostV[i] < actioncost) {
actioncost = CostV[i];
}
}
if (actioncost == INFINITECOST) {
SBPL_WARN("WARNING: actioncost = %d", actioncost);
}
solcost += actioncost;
state = state->expanded_best_parent;
wholePathIds.push_back(state->id);
}
// if we pretended that the goal was expanded for path reconstruction then
// revert the state now
if (!goal_expanded) {
goal_state->expanded_best_parent = NULL;
goal_state->v = INFINITECOST;
}
// if we searched forward then the path reconstruction worked backward from
// the goal, so we have to reverse the path
if (bforwardsearch) {
// in place reverse
for (unsigned int i = 0; i < wholePathIds.size() / 2; i++) {
int other_idx = wholePathIds.size() - i - 1;
int temp = wholePathIds[i];
wholePathIds[i] = wholePathIds[other_idx];
wholePathIds[other_idx] = temp;
}
}
return wholePathIds;
}
bool LazyARAPlanner::outOfTime()
{
// if we are supposed to run until the first solution, then we are never out
// of time
if (params.return_first_solution) {
return false;
}
double time_used = double(clock() - TimeStarted) / CLOCKS_PER_SEC;
if (time_used >= params.max_time) {
SBPL_DEBUG("out of max time");
}
if (use_repair_time && eps_satisfied != INFINITECOST && time_used >= params.repair_time) {
SBPL_DEBUG("used all repair time...");
}
// we are out of time if:
// we used up the max time limit OR
// we found some solution and used up the minimum time limit
return time_used >= params.max_time ||
(use_repair_time && eps_satisfied != INFINITECOST && time_used >= params.repair_time);
}
void LazyARAPlanner::initializeSearch()
{
// it's a new search, so increment replan_number and reset the
// search_iteration
replan_number++;
search_iteration = 0;
search_expands = 0;
totalPlanTime = 0;
totalExpands = 0;
reconstructTime = 0;
totalTime = 0;
// clear open list, incons list, and stats list
heap.makeemptyheap();
incons.clear();
stats.clear();
// initialize epsilon variable
eps = params.initial_eps;
eps_satisfied = INFINITECOST;
// call get state to initialize the start and goal states
if (bforwardsearch) {
goal_state = GetState(goal_state_id);
start_state = GetState(start_state_id);
}
else {
start_state = GetState(goal_state_id);
goal_state = GetState(start_state_id);
}
// put start state in the heap
start_state->g = 0;
CKey key;
key.key[0] = eps * start_state->h;
heap.insertheap(start_state, key);
// ensure heuristics are up-to-date
environment_->EnsureHeuristicsUpdated((bforwardsearch == true));
}
bool LazyARAPlanner::Search(vector<int>& pathIds, int& PathCost)
{
CKey key;
TimeStarted = clock();
initializeSearch();
// the main loop of ARA*
while (eps_satisfied > params.final_eps && !outOfTime()) {
// run weighted A*
clock_t before_time = clock();
int before_expands = search_expands;
// ImprovePath returns:
// 1 if the solution is found
// 0 if the solution does not exist
// 2 if it ran out of time
int ret = ImprovePath();
if (ret == 1) {
// solution found for this iteration
eps_satisfied = eps;
}
int delta_expands = search_expands - before_expands;
double delta_time = double(clock() - before_time) / CLOCKS_PER_SEC;
// print the bound, expands, and time for that iteration
SBPL_DEBUG("bound=%f expands=%d cost=%d time=%.3f", eps_satisfied, delta_expands, goal_state->g, delta_time);
// update stats
totalPlanTime += delta_time;
totalExpands += delta_expands;
PlannerStats tempStat;
tempStat.eps = eps_satisfied;
tempStat.expands = delta_expands;
tempStat.time = delta_time;
tempStat.cost = goal_state->g;
stats.push_back(tempStat);
// no solution exists
if (ret == 0) {
SBPL_DEBUG("Solution does not exist");
return false;
}
// if we're just supposed to find the first solution or if we ran out of
// time, we're done
if (params.return_first_solution || ret == 2) {
break;
}
prepareNextSearchIteration();
}
if (goal_state->g == INFINITECOST) {
SBPL_DEBUG("could not find a solution (ran out of time)");
return false;
}
if (eps_satisfied == INFINITECOST) {
SBPL_DEBUG("WARNING: a solution was found but we don't have quality bound for it!");
}
SBPL_DEBUG("solution found");
clock_t before_reconstruct = clock();
pathIds = GetSearchPath(PathCost);
reconstructTime = double(clock() - before_reconstruct) / CLOCKS_PER_SEC;
totalTime = totalPlanTime + reconstructTime;
return true;
}
void LazyARAPlanner::prepareNextSearchIteration()
{
//decrease epsilon
eps -= params.dec_eps;
if (eps < params.final_eps) {
eps = params.final_eps;
}
// dump the inconsistent states into the open list
CKey key;
while (!incons.empty()) {
LazyARAState* s = incons.back();
incons.pop_back();
s->in_incons = false;
key.key[0] = s->g + int(eps * s->h);
heap.insertheap(s,key);
}
// recompute priorities for states in OPEN and reorder it
for (int i = 1; i <= heap.currentsize; ++i){
LazyARAState* state = (LazyARAState*)heap.heap[i].heapstate;
heap.heap[i].key.key[0] = state->g + int(eps * state->h);
}
heap.makeheap();
search_iteration++;
}
//-----------------------------Interface function-------------------------------
int LazyARAPlanner::replan(
double allocated_time_secs,
std::vector<int>* solution_stateIDs_V)
{
int solcost = 0;
return replan(allocated_time_secs, solution_stateIDs_V, &solcost);
}
int LazyARAPlanner::replan(
double allocated_time_sec,
std::vector<int>* solution_stateIDs_V,
int* solcost)
{
params.max_time = allocated_time_sec;
return replan(solution_stateIDs_V, params, solcost);
}
int LazyARAPlanner::replan(
vector<int>* solution_stateIDs_V,
ReplanParams p)
{
int solcost = 0;
return replan(solution_stateIDs_V, p, &solcost);
}
int LazyARAPlanner::replan(
int start,
int goal,
vector<int>* solution_stateIDs_V,
ReplanParams p,
int* solcost)
{
set_start(start);
set_goal(goal);
return replan(solution_stateIDs_V, p, solcost);
}
int LazyARAPlanner::replan(
vector<int>* solution_stateIDs_V,
ReplanParams p,
int* solcost)
{
SBPL_DEBUG("planner: replan called");
params = p;
use_repair_time = params.repair_time >= 0;
if (goal_state_id < 0) {
SBPL_ERROR("ERROR searching: no goal state set");
return 0;
}
if (start_state_id < 0) {
SBPL_ERROR("ERROR searching: no start state set");
return 0;
}
// plan
vector<int> pathIds;
int PathCost = 0;
bool solnFound = Search(pathIds, PathCost);
SBPL_DEBUG("total expands=%d planning time=%.3f reconstruct path time=%.3f total time=%.3f solution cost=%d", totalExpands, totalPlanTime, reconstructTime, totalTime, goal_state->g);
// copy the solution
*solution_stateIDs_V = pathIds;
*solcost = PathCost;
start_state_id = -1;
goal_state_id = -1;
return (int)solnFound;
}
int LazyARAPlanner::set_goal(int id)
{
SBPL_DEBUG("planner: setting goal to %d", id);
if (bforwardsearch) {
goal_state_id = id;
}
else {
start_state_id = id;
}
return 1;
}
int LazyARAPlanner::set_start(int id)
{
SBPL_DEBUG("planner: setting start to %d", id);
if (bforwardsearch) {
start_state_id = id;
}
else {
goal_state_id = id;
}
return 1;
}
//------------------------------------------------------------------------------
void LazyARAPlanner::get_search_stats(vector<PlannerStats>* s)
{
s->clear();
s->reserve(stats.size());
for (unsigned int i = 0; i < stats.size(); i++) {
s->push_back(stats[i]);
}
}

View File

@@ -0,0 +1,654 @@
/*
* Copyright (c) 2015, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sbpl/planners/mhaplanner.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <algorithm>
#include <sbpl/utils/key.h>
static double GetTime()
{
return (double)clock() / (double)CLOCKS_PER_SEC;
}
MHAPlanner::MHAPlanner(
DiscreteSpaceInformation* environment,
Heuristic* hanchor,
Heuristic** heurs,
int hcount)
:
SBPLPlanner(),
// environment_(environment),
m_hanchor(hanchor),
m_heurs(heurs),
m_hcount(hcount),
m_params(0.0),
m_initial_eps_mha(1.0),
m_max_expansions(0),
m_eps(1.0),
m_eps_mha(1.0),
m_eps_satisfied((double)INFINITECOST),
m_num_expansions(0),
m_elapsed(0.0),
m_call_number(0), // uninitialized
m_start_state(NULL),
m_goal_state(NULL),
m_search_states(),
m_open(NULL)
{
environment_ = environment;
m_open = new CHeap[hcount + 1];
// Overwrite default members for ReplanParams to represent a single optimal
// search
m_params.initial_eps = 1.0;
m_params.final_eps = 1.0;
m_params.dec_eps = 0.2; // NOTE: same initial epsilon delta as ARA*
m_params.return_first_solution = false;
m_params.max_time = 0.0;
m_params.repair_time = 0.0;
/// Four Modes:
/// Search Until Solution Bounded
/// Search Until Solution Unbounded
/// Improve Solution Bounded
/// Improve Solution Unbounded
}
MHAPlanner::~MHAPlanner()
{
clear();
delete[] m_open;
}
int MHAPlanner::set_start(int start_stateID)
{
m_start_state = get_state(start_stateID);
if (!m_start_state) {
return 0;
}
else {
return 1;
}
}
int MHAPlanner::set_goal(int goal_stateID)
{
m_goal_state = get_state(goal_stateID);
if (!m_goal_state) {
return 0;
}
else {
return 1;
}
}
int MHAPlanner::replan(
double allocated_time_sec,
std::vector<int>* solution_stateIDs_V)
{
int solcost;
return replan(allocated_time_sec, solution_stateIDs_V, &solcost);
}
int MHAPlanner::replan(
double allocated_time_sec,
std::vector<int>* solution_stateIDs_V,
int* solcost)
{
ReplanParams params = m_params;
params.max_time = allocated_time_sec;
return replan(solution_stateIDs_V, params, solcost);
}
int MHAPlanner::replan(
std::vector<int>* solution_stateIDs_V,
ReplanParams params)
{
int solcost;
return replan(solution_stateIDs_V, params, &solcost);
}
int MHAPlanner::replan(
std::vector<int>* solution_stateIDs_V,
ReplanParams params,
int* solcost)
{
if (!check_params(params)) { // errors printed within
return 0;
}
m_params = params;
SBPL_INFO("Generic Search parameters:");
SBPL_INFO(" Initial Epsilon: %0.3f", m_params.initial_eps);
SBPL_INFO(" Final Epsilon: %0.3f", m_params.final_eps);
SBPL_INFO(" Delta Epsilon: %0.3f", m_params.dec_eps);
SBPL_INFO(" Return First Solution: %s", m_params.return_first_solution ? "true" : "false");
SBPL_INFO(" Max Time: %0.3f", m_params.max_time);
SBPL_INFO(" Repair Time: %0.3f", m_params.repair_time);
SBPL_INFO("MHA Search parameters:");
SBPL_INFO(" MHA Epsilon: %0.3f", m_initial_eps_mha);
SBPL_INFO(" Max Expansions: %d", m_max_expansions);
environment_->EnsureHeuristicsUpdated(true); // TODO: support backwards search
// TODO: pick up from where last search left off and detect lazy
// reinitializations
reinit_search();
m_eps = m_params.initial_eps;
m_eps_mha = m_initial_eps_mha;
m_eps_satisfied = (double)INFINITECOST;
// reset time limits
m_num_expansions = 0;
m_elapsed = 0.0;
double start_time, end_time;
start_time = GetTime();
++m_call_number;
reinit_state(m_goal_state);
reinit_state(m_start_state);
m_start_state->g = 0;
// insert start state into all heaps with key(start, i) as priority
for (int hidx = 0; hidx < num_heuristics(); ++hidx) {
CKey key;
key.key[0] = compute_key(m_start_state, hidx);
m_open[hidx].insertheap(&m_start_state->od[hidx].open_state, key);
SBPL_DEBUG("Inserted start state %d into search %d with f = %d", m_start_state->state_id, hidx, key.key[0]);
}
end_time = GetTime();
m_elapsed += (end_time - start_time);
while (!m_open[0].emptyheap() && !time_limit_reached()) {
start_time = GetTime();
// special case for mha* without additional heuristics
if (num_heuristics() == 1) {
if (m_goal_state->g <= get_minf(m_open[0])) {
m_eps_satisfied = m_eps * m_eps_mha;
extract_path(solution_stateIDs_V, solcost);
return 1;
}
else {
MHASearchState* s = state_from_open_state(m_open[0].getminheap());
expand(s, 0);
}
}
for (int hidx = 1; hidx < num_heuristics(); ++hidx) {
if (m_open[0].emptyheap()) {
break;
}
if (!m_open[hidx].emptyheap() && get_minf(m_open[hidx]) <=
m_eps_mha * get_minf(m_open[0]))
{
if (m_goal_state->g <= get_minf(m_open[hidx])) {
m_eps_satisfied = m_eps * m_eps_mha;
extract_path(solution_stateIDs_V, solcost);
return 1;
}
else {
MHASearchState* s =
state_from_open_state(m_open[hidx].getminheap());
expand(s, hidx);
}
}
else {
if (m_goal_state->g <= get_minf(m_open[0])) {
m_eps_satisfied = m_eps * m_eps_mha;
extract_path(solution_stateIDs_V, solcost);
return 1;
}
else {
MHASearchState* s =
state_from_open_state(m_open[0].getminheap());
expand(s, 0);
}
}
}
end_time = GetTime();
m_elapsed += (end_time - start_time);
}
if (m_open[0].emptyheap()) {
SBPL_DEBUG("Anchor search exhausted");
}
if (time_limit_reached()) {
SBPL_DEBUG("Time limit reached");
}
return 0;
}
int MHAPlanner::force_planning_from_scratch()
{
return 0;
}
int MHAPlanner::force_planning_from_scratch_and_free_memory()
{
return 0;
}
void MHAPlanner::costs_changed(StateChangeQuery const & stateChange)
{
}
void MHAPlanner::costs_changed()
{
}
int MHAPlanner::set_search_mode(bool bSearchUntilFirstSolution)
{
return m_params.return_first_solution = bSearchUntilFirstSolution;
}
void MHAPlanner::set_initialsolution_eps(double eps)
{
m_params.initial_eps = eps;
}
double MHAPlanner::get_initial_eps()
{
return m_params.initial_eps;
}
double MHAPlanner::get_solution_eps() const
{
return m_eps_satisfied;
}
double MHAPlanner::get_final_epsilon()
{
return m_eps_satisfied;
}
double MHAPlanner::get_final_eps_planning_time()
{
return m_elapsed;
}
double MHAPlanner::get_initial_eps_planning_time()
{
return m_elapsed;
}
int MHAPlanner::get_n_expands() const
{
return m_num_expansions;
}
int MHAPlanner::get_n_expands_init_solution()
{
return m_num_expansions;
}
void MHAPlanner::get_search_stats(std::vector<PlannerStats>* s)
{
}
void MHAPlanner::set_initial_mha_eps(double eps)
{
m_initial_eps_mha = eps;
}
void MHAPlanner::set_final_eps(double eps)
{
m_params.final_eps = eps;
}
void MHAPlanner::set_dec_eps(double eps)
{
m_params.dec_eps = eps;
}
void MHAPlanner::set_max_expansions(int expansion_count)
{
m_max_expansions = expansion_count;
}
void MHAPlanner::set_max_time(double max_time)
{
m_params.max_time = max_time;
}
double MHAPlanner::get_initial_mha_eps() const
{
return m_initial_eps_mha;
}
double MHAPlanner::get_final_eps() const
{
return m_params.final_eps;
}
double MHAPlanner::get_dec_eps() const
{
return m_params.dec_eps;
}
int MHAPlanner::get_max_expansions() const
{
return m_max_expansions;
}
double MHAPlanner::get_max_time() const
{
return m_params.max_time;
}
bool MHAPlanner::check_params(const ReplanParams& params)
{
if (params.initial_eps < 1.0) {
SBPL_ERROR("Initial Epsilon must be greater than or equal to 1");
return false;
}
if (params.final_eps > params.initial_eps) {
SBPL_ERROR("Final Epsilon must be less than or equal to initial epsilon");
return false;
}
if (params.dec_eps <= 0.0) {
SBPL_ERROR("Delta epsilon must be strictly positive");
return false;
}
if (m_initial_eps_mha < 1.0) {
SBPL_ERROR("MHA Epsilon must be greater than or equal to 1");
return false;
}
if (params.return_first_solution &&
params.max_time <= 0.0 &&
m_max_expansions <= 0)
{
SBPL_ERROR("Max Time or Max Expansions must be positive");
return false;
}
return true;
}
bool MHAPlanner::time_limit_reached() const
{
if (m_params.return_first_solution) {
return false;
}
else if (m_params.max_time > 0.0 && m_elapsed >= m_params.max_time) {
return true;
}
else if (m_max_expansions > 0 && m_num_expansions >= m_max_expansions) {
return true;
}
else {
return false;
}
}
MHASearchState* MHAPlanner::get_state(int state_id)
{
assert(state_id >= 0 && state_id < environment_->StateID2IndexMapping.size());
int* idxs = environment_->StateID2IndexMapping[state_id];
if (idxs[MHAMDP_STATEID2IND] == -1) {
// overallocate search state for appropriate heuristic information
const size_t state_size =
sizeof(MHASearchState) +
sizeof(MHASearchState::HeapData) * (m_hcount);
MHASearchState* s = (MHASearchState*)malloc(state_size);
const size_t mha_state_idx = m_search_states.size();
init_state(s, mha_state_idx, state_id);
// map graph state to search state
idxs[MHAMDP_STATEID2IND] = mha_state_idx;
m_search_states.push_back(s);
return s;
}
else {
int ssidx = idxs[MHAMDP_STATEID2IND];
return m_search_states[ssidx];
}
}
void MHAPlanner::clear()
{
clear_open_lists();
// free states
for (size_t i = 0; i < m_search_states.size(); ++i) {
// unmap graph to search state
const int state_id = m_search_states[i]->state_id;
int* idxs = environment_->StateID2IndexMapping[state_id];
idxs[MHAMDP_STATEID2IND] = -1;
// free search state
free(m_search_states[i]);
}
// empty state table
m_search_states.clear();
m_start_state = NULL;
m_goal_state = NULL;
}
void MHAPlanner::init_state(
MHASearchState* state,
size_t mha_state_idx,
int state_id)
{
state->call_number = 0; // not initialized for any iteration
state->state_id = state_id;
state->closed_in_anc = false;
state->closed_in_add = false;
for (int i = 0; i < num_heuristics(); ++i) {
state->od[i].open_state.heapindex = 0;
state->od[i].h = compute_heuristic(state->state_id, i);
// hijack list element pointers to map back to mha search state
assert(sizeof(state->od[i].open_state.listelem) >= sizeof(struct listelement*));
reinterpret_cast<size_t&>(state->od[i].open_state.listelem[0]) = mha_state_idx;
}
}
void MHAPlanner::reinit_state(MHASearchState* state)
{
if (state->call_number != m_call_number) {
state->call_number = m_call_number;
state->g = INFINITECOST;
state->bp = NULL;
state->closed_in_anc = false;
state->closed_in_add = false;
for (int i = 0; i < num_heuristics(); ++i) {
state->od[i].open_state.heapindex = 0;
state->od[i].h = compute_heuristic(state->state_id, i);
}
}
}
void MHAPlanner::reinit_search()
{
clear_open_lists();
}
void MHAPlanner::clear_open_lists()
{
for (int i = 0; i < num_heuristics(); ++i) {
m_open[i].makeemptyheap();
}
}
int MHAPlanner::compute_key(MHASearchState* state, int hidx)
{
return state->g + m_eps * state->od[hidx].h;
}
void MHAPlanner::expand(MHASearchState* state, int hidx)
{
SBPL_DEBUG("Expanding state %d in search %d", state->state_id, hidx);
assert(!closed_in_add_search(state) || !closed_in_anc_search(state));
if (hidx == 0) {
state->closed_in_anc = true;
}
else {
state->closed_in_add = true;
}
++m_num_expansions;
// remove s from all open lists
for (int temp_hidx = 0; temp_hidx < num_heuristics(); ++temp_hidx) {
if (m_open[temp_hidx].inheap(&state->od[temp_hidx].open_state)) {
m_open[temp_hidx].deleteheap(&state->od[temp_hidx].open_state);
}
}
std::vector<int> succ_ids;
std::vector<int> costs;
environment_->GetSuccs(state->state_id, &succ_ids, &costs);
assert(succ_ids.size() == costs.size());
for (size_t sidx = 0; sidx < succ_ids.size(); ++sidx) {
const int cost = costs[sidx];
MHASearchState* succ_state = get_state(succ_ids[sidx]);
reinit_state(succ_state);
SBPL_DEBUG(" Successor %d", succ_state->state_id);
int new_g = state->g + costs[sidx];
if (new_g < succ_state->g) {
succ_state->g = new_g;
succ_state->bp = state;
if (!closed_in_anc_search(succ_state)) {
const int fanchor = compute_key(succ_state, 0);
insert_or_update(succ_state, 0, fanchor);
SBPL_DEBUG(" Update in search %d with f = %d", 0, fanchor);
if (!closed_in_add_search(succ_state)) {
for (int temp_hidx = 1; temp_hidx < num_heuristics(); ++temp_hidx) {
int fn = compute_key(succ_state, temp_hidx);
if (fn <= m_eps_mha * fanchor) {
insert_or_update(succ_state, temp_hidx, fn);
SBPL_DEBUG(" Update in search %d with f = %d", temp_hidx, fn);
}
else {
SBPL_DEBUG(" Skipping update of in search %d (%0.3f > %0.3f)", temp_hidx, (double)fn, m_eps_mha * fanchor);
}
}
}
}
}
}
assert(closed_in_any_search(state));
}
MHASearchState* MHAPlanner::state_from_open_state(
AbstractSearchState* open_state)
{
const size_t ssidx = reinterpret_cast<size_t>(open_state->listelem[0]);
return m_search_states[ssidx];
}
int MHAPlanner::compute_heuristic(int state_id, int hidx)
{
if (hidx == 0) {
return m_hanchor->GetGoalHeuristic(state_id);
}
else {
return m_heurs[hidx - 1]->GetGoalHeuristic(state_id);
}
}
int MHAPlanner::get_minf(CHeap& pq) const
{
return pq.getminkeyheap().key[0];
}
void MHAPlanner::insert_or_update(MHASearchState* state, int hidx, int f)
{
CKey new_key;
new_key.key[0] = f;
if (state->od[hidx].open_state.heapindex != 0) {
m_open[hidx].updateheap(&state->od[hidx].open_state, new_key);
}
else {
m_open[hidx].insertheap(&state->od[hidx].open_state, new_key);
}
}
void MHAPlanner::extract_path(std::vector<int>* solution_path, int* solcost)
{
SBPL_DEBUG("Extracting path");
solution_path->clear();
*solcost = 0;
for (MHASearchState* state = m_goal_state; state; state = state->bp)
{
solution_path->push_back(state->state_id);
if (state->bp) {
*solcost += (state->g - state->bp->g);
}
}
// TODO: special cases for backward search
std::reverse(solution_path->begin(), solution_path->end());
}
bool MHAPlanner::closed_in_anc_search(MHASearchState* state) const
{
return state->closed_in_anc;
}
bool MHAPlanner::closed_in_add_search(MHASearchState* state) const
{
return state->closed_in_add;
}
bool MHAPlanner::closed_in_any_search(MHASearchState* state) const
{
return state->closed_in_anc || state->closed_in_add;
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 2009, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sbpl/discrete_space_information/environment.h>
#include <sbpl/planners/ppcpplanner.h>
using namespace std;
//-----------------------------------------------------------------------------------------------------
PPCPPlanner::PPCPPlanner(DiscreteSpaceInformation* environment, int sizeofS, int sizeofH)
{
environment_ = environment;
#ifndef ROS
const char* debug = "debug.txt";
#endif
fDeb = SBPL_FOPEN(debug, "w");
if (fDeb == NULL) {
throw SBPL_Exception("ERROR: could not open planner debug file");
}
pStateSpace = new PPCPStateSpace_t;
//TODO - create and initialize the state-space
}
PPCPPlanner::~PPCPPlanner()
{
if (pStateSpace != NULL) {
//delete the statespace
DeleteStateSpace( pStateSpace);
delete pStateSpace;
pStateSpace = NULL;
}
SBPL_FCLOSE( fDeb);
}
//deallocates memory used by StateSpace
void PPCPPlanner::DeleteStateSpace(PPCPStateSpace_t* pStateSpace)
{
//TODO - fill in
}
//creates (allocates memory) search state space
//does not initialize search statespace
int PPCPPlanner::CreateSearchStateSpace(PPCPStateSpace_t* pStateSpace)
{
//create a heap
pStateSpace->bReinitializeSearchStateSpace = true;
pStateSpace->currentpolicyconfidence = 0;
pStateSpace->GoalState = NULL;
pStateSpace->StartState = NULL;
pStateSpace->iteration = 0;
pStateSpace->searchiteration = 0;
return 1;
}
//--------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
//setting start state in S
int PPCPPlanner::set_goal(int goal_stateID)
{
//TODO
return 1;
}
//setting goal state in S
int PPCPPlanner::set_start(int start_stateID)
{
//TODO
return 1;
}
void PPCPPlanner::costs_changed(StateChangeQuery const & stateChange)
{
SBPL_PRINTF("planner: costs_changed, state-space reset\n");
pStateSpace->bReinitializeSearchStateSpace = true;
}
void PPCPPlanner::costs_changed()
{
SBPL_PRINTF("planner: costs_changed, state-space reset\n");
pStateSpace->bReinitializeSearchStateSpace = true;
}
int PPCPPlanner::force_planning_from_scratch()
{
SBPL_PRINTF("planner: forceplanfromscratch set, state-space reset\n");
pStateSpace->bReinitializeSearchStateSpace = true;
return 1;
}
int PPCPPlanner::replan(double allocated_time_secs, vector<sbpl_PolicyStatewithBinaryh_t>* SolutionPolicy,
float* ExpectedCost, float* ProbofReachGoal)
{
//TODO
return 0;
}
//-------------------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,410 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <cmath>
#include <sbpl/discrete_space_information/environment.h>
#include <sbpl/planners/viplanner.h>
#include <sbpl/utils/key.h>
#include <sbpl/utils/mdpconfig.h>
#include <sbpl/utils/utils.h>
using namespace std;
static unsigned int g_backups;
static clock_t g_runtime = 0;
static double g_belldelta = INFINITECOST;
VIPlanner::~VIPlanner()
{
//delete the statespace
}
void VIPlanner::Initialize_vidata(CMDPSTATE* state)
{
VIState* vi_data = (VIState*)state->PlannerSpecificData;
vi_data->bestnextaction = NULL;
vi_data->iteration = 0;
vi_data->v = (float)environment_->GetGoalHeuristic(state->StateID);
}
CMDPSTATE* VIPlanner::CreateState(int stateID)
{
CMDPSTATE* state = NULL;
#if DEBUG
if (environment_->StateID2IndexMapping[stateID][VIMDP_STATEID2IND] != -1) {
throw SBPL_Exception("ERROR in CreateState: state already created");
}
#endif
//adds to the tail a state
state = viPlanner.MDP.AddState(stateID);
//remember the index of the state
environment_->StateID2IndexMapping[stateID][VIMDP_STATEID2IND] = viPlanner.MDP.StateArray.size() - 1;
#if DEBUG
if (state != viPlanner.MDP.StateArray[environment_->StateID2IndexMapping[stateID][VIMDP_STATEID2IND]]) {
throw SBPL_Exception("ERROR in CreateState: invalid state index");
}
#endif
//create and initialize vi_data
state->PlannerSpecificData = new VIState;
Initialize_vidata(state);
return state;
}
CMDPSTATE* VIPlanner::GetState(int stateID)
{
if (stateID >= (int)environment_->StateID2IndexMapping.size()) {
throw SBPL_Exception("ERROR in GetState: stateID is invalid");
}
if (environment_->StateID2IndexMapping[stateID][VIMDP_STATEID2IND] == -1)
return CreateState(stateID);
else
return viPlanner.MDP.StateArray[environment_->StateID2IndexMapping[stateID][VIMDP_STATEID2IND]];
}
void VIPlanner::PrintVIData()
{
SBPL_PRINTF("iteration %d: v(start) = %f\n", viPlanner.iteration,
((VIState*)(viPlanner.StartState->PlannerSpecificData))->v);
}
void VIPlanner::PrintStatHeader(FILE* fOut)
{
SBPL_FPRINTF(fOut, "iteration backups v(start)\n");
}
void VIPlanner::PrintStat(FILE* fOut, clock_t starttime)
{
SBPL_FPRINTF(fOut, "%d %d %f %f %d\n", viPlanner.iteration, g_backups,
((double)(clock() - starttime)) / CLOCKS_PER_SEC,
((VIState*)(viPlanner.StartState->PlannerSpecificData))->v,
(unsigned int)viPlanner.MDP.StateArray.size());
}
void VIPlanner::PrintPolicy(FILE* fPolicy)
{
bool bPrintStatOnly = true;
vector<CMDPSTATE*> WorkList;
CMDP PolicyforEvaluation;
viPlanner.iteration++;
WorkList.push_back(viPlanner.StartState);
((VIState*)viPlanner.StartState->PlannerSpecificData)->iteration = viPlanner.iteration;
double PolVal = 0.0;
double Conf = 0;
bool bCycles = false;
SBPL_PRINTF("Printing policy...\n");
while ((int)WorkList.size() > 0) {
//pop the last state
CMDPSTATE* state = WorkList.at(WorkList.size() - 1);
WorkList.pop_back();
VIState* statedata = (VIState*)state->PlannerSpecificData;
CMDPSTATE* polstate = PolicyforEvaluation.AddState(state->StateID);
//print state ID
if (!bPrintStatOnly) {
SBPL_FPRINTF(fPolicy, "%d\n", state->StateID);
environment_->PrintState(state->StateID, false, fPolicy);
int h = environment_->GetGoalHeuristic(state->StateID);
SBPL_FPRINTF(fPolicy, "h=%d\n", h);
if (h > statedata->v) {
SBPL_FPRINTF(fPolicy, "WARNING h overestimates exp.cost\n");
}
}
if (state->StateID == viPlanner.GoalState->StateID) {
//goal state
if (!bPrintStatOnly) SBPL_FPRINTF(fPolicy, "0\n");
Conf += ((VIState*)state->PlannerSpecificData)->Pc;
}
else if (statedata->bestnextaction == NULL) {
//unexplored
if (!bPrintStatOnly) {
//no outcome explored - stay in the same place
SBPL_FPRINTF(fPolicy, "%d %d %d\n", 1, 0, state->StateID);
}
}
else {
//get best action
CMDPACTION* action = statedata->bestnextaction;
//add action to evaluation MDP
CMDPACTION* polaction = polstate->AddAction(action->ActionID);
if (!bPrintStatOnly) SBPL_FPRINTF(fPolicy, "%d ", (unsigned int)action->SuccsID.size());
//print successors and insert them into the list
for (int i = 0; i < (int)action->SuccsID.size(); i++) {
if (!bPrintStatOnly) SBPL_FPRINTF(fPolicy, "%d %d ", action->Costs[i], action->SuccsID[i]);
polaction->AddOutcome(action->SuccsID[i], action->Costs[i], action->SuccsProb[i]);
CMDPSTATE* succstate = GetState(action->SuccsID[i]);
if ((int)((VIState*)succstate->PlannerSpecificData)->iteration != viPlanner.iteration) {
((VIState*)succstate->PlannerSpecificData)->iteration = viPlanner.iteration;
WorkList.push_back(succstate);
((VIState*)succstate->PlannerSpecificData)->Pc = action->SuccsProb[i] *
((VIState*)state->PlannerSpecificData)->Pc;
PolVal += ((VIState*)succstate->PlannerSpecificData)->Pc * action->Costs[i];
}
}
if (!bPrintStatOnly) SBPL_FPRINTF(fPolicy, "\n");
}
}//while worklist not empty
SBPL_PRINTF("done\n");
//now evaluate the policy
double PolicyValue = -1;
bool bFullPolicy = false;
double Pcgoal = -1;
int nMerges = 0;
EvaluatePolicy(&PolicyforEvaluation, viPlanner.StartState->StateID, viPlanner.GoalState->StateID, &PolicyValue,
&bFullPolicy, &Pcgoal, &nMerges, &bCycles);
SBPL_PRINTF("Policy value = %f FullPolicy=%d Merges=%d Cycles=%d\n", PolicyValue, bFullPolicy, nMerges, bCycles);
if (!bFullPolicy) SBPL_PRINTF("WARN: POLICY IS ONLY PARTIAL\n");
if (fabs(PolicyValue - ((VIState*)(viPlanner.StartState->PlannerSpecificData))->v) > MDP_ERRDELTA) {
SBPL_PRINTF("WARN: POLICY VALUE IS NOT CORRECT\n");
}
if (!bPrintStatOnly)
SBPL_FPRINTF(fPolicy,
"backups=%d runtime=%f vstart=%f policyvalue=%f fullpolicy=%d Pc(goal)=%f nMerges=%d bCyc=%d\n",
g_backups, (double)g_runtime / CLOCKS_PER_SEC,
((VIState*)(viPlanner.StartState->PlannerSpecificData))->v, PolicyValue, bFullPolicy, Pcgoal,
nMerges, bCycles);
else
SBPL_FPRINTF(fPolicy, "%d %f %f %f %d %f %d %d\n", g_backups, (double)g_runtime / CLOCKS_PER_SEC,
((VIState*)(viPlanner.StartState->PlannerSpecificData))->v, PolicyValue, bFullPolicy, Pcgoal,
nMerges, bCycles);
}
void VIPlanner::backup(CMDPSTATE* state)
{
int aind, oind;
CMDPSTATE* succstate;
g_backups++;
if (state == viPlanner.GoalState) {
((VIState*)(state->PlannerSpecificData))->bestnextaction = NULL;
((VIState*)(state->PlannerSpecificData))->v = 0;
return;
}
//iterate through actions
double minactionQ = INFINITECOST;
CMDPACTION* minaction = NULL;
for (aind = 0; aind < (int)state->Actions.size(); aind++) {
double actionQ = 0;
CMDPACTION* action = state->Actions[aind];
for (oind = 0; oind < (int)action->SuccsID.size(); oind++) {
succstate = GetState(action->SuccsID[oind]);
actionQ += action->SuccsProb[oind] * (action->Costs[oind] +
((VIState*)(succstate->PlannerSpecificData))->v);
}
if (minaction == NULL || actionQ < minactionQ) {
minactionQ = actionQ;
minaction = action;
}
}
if (((VIState*)state->PlannerSpecificData)->bestnextaction == NULL)
g_belldelta = INFINITECOST;
else if (g_belldelta < fabs(((VIState*)state->PlannerSpecificData)->v - minactionQ))
g_belldelta = fabs(((VIState*)state->PlannerSpecificData)->v - minactionQ);
//set state values
((VIState*)state->PlannerSpecificData)->bestnextaction = minaction;
((VIState*)state->PlannerSpecificData)->v = (float)minactionQ;
}
void VIPlanner::perform_iteration_backward()
{
CMDPSTATE* state;
vector<int> Worklist;
int aind, oind;
//initialize the worklist
Worklist.push_back(viPlanner.GoalState->StateID);
//backup all the states
while ((int)Worklist.size() > 0) {
//get the next state to process
state = GetState(Worklist[Worklist.size() - 1]);
Worklist.pop_back();
//add all actions to the state
if ((int)state->Actions.size() == 0) environment_->SetAllActionsandAllOutcomes(state);
//backup the state
backup(state);
//insert all the not yet processed successors into the worklist
for (aind = 0; aind < (int)state->Actions.size(); aind++) {
CMDPACTION* action = state->Actions[aind];
for (oind = 0; oind < (int)action->SuccsID.size(); oind++) {
CMDPSTATE* succstate = GetState(action->SuccsID[oind]);
//skip if already was in the queue
if ((int)((VIState*)succstate->PlannerSpecificData)->iteration != viPlanner.iteration) {
Worklist.push_back(succstate->StateID);
//mark it
((VIState*)succstate->PlannerSpecificData)->iteration = viPlanner.iteration;
}
}
}
//it is not necessary to process the predecessors of the start state
if (state == viPlanner.StartState) continue;
//add all predecessor ids to the state
if ((int)state->PredsID.size() == 0) environment_->SetAllPreds(state);
//insert all the not yet processed predecessors into the worklist
for (int pind = 0; pind < (int)state->PredsID.size(); pind++) {
CMDPSTATE* PredState = GetState(state->PredsID[pind]);
//skip if already was in the queue
if ((int)((VIState*)PredState->PlannerSpecificData)->iteration != viPlanner.iteration) {
Worklist.push_back(PredState->StateID);
//mark it
((VIState*)PredState->PlannerSpecificData)->iteration = viPlanner.iteration;
}
}
} //until empty worklist
}
void VIPlanner::perform_iteration_forward()
{
CMDPSTATE* state = NULL;
vector<CMDPSTATE*> Worklist;
int aind, oind;
//initialize the worklist
Worklist.push_back(viPlanner.StartState);
//backup all the states
while ((int)Worklist.size() > 0) {
//get the next state to process from the front
state = Worklist[Worklist.size() - 1];
//Env_PrintState(state->StateID);
Worklist.pop_back();
//add all actions to the state
if ((int)state->Actions.size() == 0) environment_->SetAllActionsandAllOutcomes(state);
//backup the state
backup(state);
//insert all the not yet processed successors into the worklist
for (aind = 0; aind < (int)state->Actions.size(); aind++) {
//CMDPACTION* action = state->Actions[aind];
CMDPACTION* action = ((VIState*)state->PlannerSpecificData)->bestnextaction;
for (oind = 0; action != NULL && oind < (int)action->SuccsID.size(); oind++) {
CMDPSTATE* succstate = GetState(action->SuccsID[oind]);
//skip if already was in the queue
if ((int)((VIState*)succstate->PlannerSpecificData)->iteration != viPlanner.iteration) {
Worklist.push_back(succstate);
//mark it
((VIState*)succstate->PlannerSpecificData)->iteration = viPlanner.iteration;
}
}
}
} //until empty worklist
}
void VIPlanner::InitializePlanner()
{
viPlanner.iteration = 0;
//create and set up goal and start states
viPlanner.StartState = GetState(MDPCfg_->startstateid);
viPlanner.GoalState = GetState(MDPCfg_->goalstateid);
}
//the planning entry point
//returns 1 if path is found, 0 otherwise
int VIPlanner::replan(double allocatedtime, vector<int>* solution_stateIDs_V)
{
#ifndef ROS
const char* policy = "policy.txt";
const char* stat = "stat.txt";
#endif
FILE* fPolicy = SBPL_FOPEN(policy, "w");
FILE* fStat = SBPL_FOPEN(stat, "w");
//initialization
InitializePlanner();
//start the timer
clock_t starttime = clock();
//--------------iterate-------------------------------
while (((clock() - starttime) / (double)CLOCKS_PER_SEC) < allocatedtime && g_belldelta > MDP_ERRDELTA) {
viPlanner.iteration++;
g_belldelta = 0;
perform_iteration_forward();
if (viPlanner.iteration % 100 == 0) {
PrintStat(stdout, starttime);
PrintStat(fStat, starttime);
}
}
//------------------------------------------------------------------
g_runtime = clock() - starttime;
PrintStat(stdout, starttime);
PrintStat(fStat, starttime);
SBPL_FFLUSH(fStat);
PrintPolicy(fPolicy);
SBPL_FCLOSE(fPolicy);
SBPL_FCLOSE(fStat);
return 1;
}

View File

@@ -0,0 +1,19 @@
discretization(cells): 15 15
start(cells): 0 0
end(cells): 14 14
environment:
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
1 1 1 1 0 0 0 0 0 0 0 1 0 0 0
1 1 1 1 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0

View File

@@ -0,0 +1,23 @@
X=0 Y=0
X=1 Y=1
X=2 Y=2
X=3 Y=3
X=4 Y=4
X=5 Y=5
X=6 Y=5
X=7 Y=5
X=8 Y=5
X=9 Y=5
X=10 Y=5
X=11 Y=5
X=12 Y=5
X=12 Y=6
X=12 Y=7
X=12 Y=8
X=12 Y=9
X=13 Y=10
X=13 Y=11
X=13 Y=12
X=14 Y=13
the state is a goal state
X=14 Y=14

1610
navigations/sbpl/src/test/main.cpp Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <string>
#include <fstream>
#include <gtest/gtest.h>
using namespace std;
#include "../headers.h"
static const std::string PATH_PREFIX("src/test/");
void diffTest(const std::string& outputStr)
{
std::string validOutputStr(outputStr + ".valid");
std::ifstream validFile(validOutputStr.c_str());
// If there is no valid file then generate one.
if (!validFile.good()) {
std::ifstream newOutputFile(outputStr.c_str());
std::stringbuf sbuf;
newOutputFile >> &sbuf;
std::ofstream newValidFile(validOutputStr.c_str());
newValidFile << sbuf.str();
}
else { // Verify output against the valid file.
std::stringbuf newStrBuf, validStrBuf;
std::ifstream fNew(outputStr.c_str()), fValid(validOutputStr.c_str());
fNew >> &newStrBuf;
fValid >> &validStrBuf;
ASSERT_EQ(newStrBuf.str() == validStrBuf.str(), true);
}
}
void runARAPlannerTest(const std::string& problem)
{
try {
double allocated_time_secs = 0.5; // in seconds
MDPConfig MDPCfg;
EnvironmentNAV2D environment_nav2D;
std::string problemStr = PATH_PREFIX + problem;
ASSERT_EQ(environment_nav2D.InitializeEnv(problemStr.c_str()), true);
ASSERT_EQ(environment_nav2D.InitializeMDPCfg(&MDPCfg), true);
// plan a path
vector<int> solution_stateIDs_V;
ARAPlanner ara_planner(&environment_nav2D, false);
ASSERT_EQ(ara_planner.set_start(MDPCfg.startstateid), true);
ASSERT_EQ(ara_planner.set_goal(MDPCfg.goalstateid), true);
ASSERT_EQ(ara_planner.replan(allocated_time_secs, &solution_stateIDs_V), true);
// output the path
std::string outputStr = problemStr + ".out";
FILE* fSol = SBPL_FOPEN(outputStr.c_str(), "w");
for (unsigned int i = 0; i < solution_stateIDs_V.size(); i++) {
environment_nav2D.PrintState(solution_stateIDs_V[i], true, fSol);
}
SBPL_FCLOSE(fSol);
// Now apply the file diff test
diffTest(outputStr);
}
catch (...) {
FAIL() << "Uncaught exception : " << "This is OK on OS X";
}
}
TEST(araplanner, env1)
{
runARAPlannerTest("env1.cfg");
}
int main(int argc, char *argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <cmath>
#include <iostream>
using namespace std;
#include <sbpl/discrete_space_information/environment_precomputed_adjacency_list.h>
// 2d Points
struct Point2D
{
Point2D(int newX, int newY) :
x(newX), y(newY)
{
}
int heuristicDistanceTo(const Point2D& p)
{
int dx = p.x - x;
int dy = p.y - y;
int dist = ((int)sqrt(dx * dx + dy * dy));
return dist;
}
int x;
int y;
};
ostream& operator<<(ostream& stream, Point2D p)
{
stream << "(" << p.x << ", " << p.y << ")";
return stream;
}
int operator<(const Point2D& p1, const Point2D& p2)
{
return (p1.x < p2.x) || ((p1.x == p2.x) && (p1.y < p2.y));
}
void testPlanner(AdjacencyListSBPLEnv<Point2D>& e)
{
int sol_cost;
e.writeToStream();
vector<Point2D> solution = e.findOptimalPath(&sol_cost);
cout << "Returned plan is ";
for (unsigned int i = 0; i < solution.size(); i++) {
cout << solution[i] << " ";
}
cout << endl;
}
int main(int, char**)
{
AdjacencyListSBPLEnv<Point2D> e;
Point2D p1(0, 0);
Point2D p2(2, 1);
Point2D p3(1, 4);
Point2D p4(5, 5);
e.addPoint(p1);
e.addPoint(p4);
e.addPoint(p3);
e.addPoint(p2);
e.setCost(p1, p2, 4);
e.setCost(p1, p3, 6);
e.setCost(p3, p4, 5);
e.setCost(p2, p4, 15);
e.setStartState(p1);
e.setGoalState(p4);
// Initialize the MDPConfig (what does this do exactly?)
//MDPConfig c;
//e.InitializeMDPCfg(&c);
// Tests
testPlanner(e);
e.setCost(p2, p4, 1);
testPlanner(e);
e.removeLastPoints();
testPlanner(e);
e.writeToStream();
return 0;
}

View File

@@ -0,0 +1,882 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <cstdio>
#include <ctime>
#include <sstream>
#include <sbpl/utils/2Dgridsearch.h>
#include <sbpl/utils/heap.h>
#include <sbpl/utils/list.h>
using namespace std;
// Creating custom getCost functions that will combine multiple cells in the main grid
// into a single cell in the 2D grid.
// Using templates for common cases so the compiler can generate faster code
template<int N>
unsigned char getCostT(unsigned char **Grid2D, int x, int y, int /*resample*/)
{
if(N == 1) // the compiler will optimize out this if statement
{
return Grid2D[x][y];
}
else
{
x *= N;
y *= N;
unsigned char maximum = Grid2D[x][y];
for(int dy=0; dy<N; dy++)
for(int dx=0; dx<N; dx++)
maximum = __max(maximum, Grid2D[x+dx][y+dy]);
return maximum;
}
}
// fallback for unforseen cases
unsigned char getCostN(unsigned char **Grid2D, int x, int y, int resample)
{
x *= resample;
y *= resample;
unsigned char maximum = Grid2D[x][y];
for(int dy=0; dy<resample; dy++)
for(int dx=0; dx<resample; dx++)
maximum = __max(maximum, Grid2D[x+dx][y+dy]);
return maximum;
}
//---------------------initialization and destruction routines--------------------------------------------------------
SBPL2DGridSearch::SBPL2DGridSearch(int width_x, int height_y, float cellsize_m, int downsample, int initial_dynamic_bucket_size)
{
iteration_ = 0;
searchStates2D_ = NULL;
downsample_ = __max(1, downsample);
width_ = width_x / downsample;
height_ = height_y / downsample;
cellSize_m_ = cellsize_m * downsample;
// choose appropriate hard-coded getCost for resample amount
switch(downsample_)
{
case 1: getCost = &getCostT<1>; break;
case 2: getCost = &getCostT<2>; break;
case 3: getCost = &getCostT<3>; break;
case 4: getCost = &getCostT<4>; break;
case 5: getCost = &getCostT<5>; break;
default:
getCost = &getCostN;
}
startX_ = -1;
startY_ = -1;
goalX_ = -1;
goalY_ = -1;
largestcomputedoptf_ = 0;
//compute dx, dy, dxintersects and dyintersects arrays
computedxy();
term_condition_usedlast = SBPL_2DGRIDSEARCH_TERM_CONDITION_ALLCELLS;
//allocate memory
OPEN2D_ = new CIntHeap(width_ * height_);
if (!createSearchStates2D()) {
throw SBPL_Exception("ERROR: failed to create searchstatespace2D");
}
//by default, OPEN is implemented as heap
OPEN2DBLIST_ = NULL;
OPENtype_ = SBPL_2DGRIDSEARCH_OPENTYPE_HEAP;
initial_dynamic_bucket_size_ = initial_dynamic_bucket_size;
}
bool SBPL2DGridSearch::setOPENdatastructure(SBPL_2DGRIDSEARCH_OPENTYPE OPENtype)
{
OPENtype_ = OPENtype;
switch (OPENtype_) {
case SBPL_2DGRIDSEARCH_OPENTYPE_HEAP:
//this is the default, nothing else needs to be done
break;
case SBPL_2DGRIDSEARCH_OPENTYPE_SLIDINGBUCKETS:
SBPL_PRINTF("setting OPEN2D data structure to sliding buckets\n");
if (OPEN2DBLIST_ == NULL) {
//create sliding buckets
//compute max distance for edge
int maxdistance = 0;
for (int dind = 0; dind < SBPL_2DGRIDSEARCH_NUMOF2DDIRS; dind++) {
maxdistance = __max(maxdistance, dxy_distance_mm_[dind]);
}
int bucketsize = __max(1000, this->width_ + this->height_);
int numofbuckets = 255 * maxdistance;
SBPL_PRINTF("creating sliding bucket-based OPEN2D %d buckets, each bucket of size %d ...", numofbuckets,
bucketsize);
OPEN2DBLIST_ = new CSlidingBucket(numofbuckets, bucketsize, initial_dynamic_bucket_size_);
SBPL_PRINTF("done\n");
}
//delete other data structures
if (OPEN2D_ != NULL) {
OPEN2D_->makeemptyheap();
delete OPEN2D_;
OPEN2D_ = NULL;
}
break;
default:
std::stringstream ss("ERROR: unknown data structure type = ");
ss << OPENtype_ << " for OPEN2D";
throw SBPL_Exception(ss.str());
};
return true;
}
bool SBPL2DGridSearch::createSearchStates2D(void)
{
int x, y;
if (searchStates2D_ != NULL) {
SBPL_ERROR("ERROR: We already have a non-NULL search states array\n");
return false;
}
searchStates2D_ = new SBPL_2DGridSearchState*[width_];
for (x = 0; x < width_; x++) {
searchStates2D_[x] = new SBPL_2DGridSearchState[height_];
for (y = 0; y < height_; y++) {
searchStates2D_[x][y].iterationaccessed = iteration_;
searchStates2D_[x][y].x = x;
searchStates2D_[x][y].y = y;
initializeSearchState2D(&searchStates2D_[x][y]);
}
}
return true;
}
inline void SBPL2DGridSearch::initializeSearchState2D(SBPL_2DGridSearchState* state2D)
{
state2D->g = INFINITECOST;
state2D->heapindex = 0;
state2D->iterationaccessed = iteration_;
}
void SBPL2DGridSearch::destroy()
{
// destroy the OPEN list:
if (OPEN2D_ != NULL) {
OPEN2D_->makeemptyheap();
delete OPEN2D_;
OPEN2D_ = NULL;
}
// destroy the 2D states:
if (searchStates2D_ != NULL) {
for (int x = 0; x < width_; x++) {
delete[] searchStates2D_[x];
}
delete[] searchStates2D_;
searchStates2D_ = NULL;
}
if (OPEN2DBLIST_ != NULL) {
delete OPEN2DBLIST_;
OPEN2DBLIST_ = NULL;
}
}
void SBPL2DGridSearch::computedxy()
{
//initialize some constants for 2D search
dx_[0] = 1;
dy_[0] = 1;
dx0intersects_[0] = -1;
dy0intersects_[0] = -1;
dx_[1] = 1;
dy_[1] = 0;
dx0intersects_[1] = -1;
dy0intersects_[1] = -1;
dx_[2] = 1;
dy_[2] = -1;
dx0intersects_[2] = -1;
dy0intersects_[2] = -1;
dx_[3] = 0;
dy_[3] = 1;
dx0intersects_[3] = -1;
dy0intersects_[3] = -1;
dx_[4] = 0;
dy_[4] = -1;
dx0intersects_[4] = -1;
dy0intersects_[4] = -1;
dx_[5] = -1;
dy_[5] = 1;
dx0intersects_[5] = -1;
dy0intersects_[5] = -1;
dx_[6] = -1;
dy_[6] = 0;
dx0intersects_[6] = -1;
dy0intersects_[6] = -1;
dx_[7] = -1;
dy_[7] = -1;
dx0intersects_[7] = -1;
dy0intersects_[7] = -1;
//Note: these actions have to be starting at 8 and through 15, since they
//get multiplied correspondingly in Dijkstra's search based on index
#if SBPL_2DGRIDSEARCH_NUMOF2DDIRS == 16
dx_[8] = 2; dy_[8] = 1;
dx0intersects_[8] = 1; dy0intersects_[8] = 0; dx1intersects_[8] = 1; dy1intersects_[8] = 1;
dx_[9] = 1; dy_[9] = 2;
dx0intersects_[9] = 0; dy0intersects_[9] = 1; dx1intersects_[9] = 1; dy1intersects_[9] = 1;
dx_[10] = -1; dy_[10] = 2;
dx0intersects_[10] = 0; dy0intersects_[10] = 1; dx1intersects_[10] = -1; dy1intersects_[10] = 1;
dx_[11] = -2; dy_[11] = 1;
dx0intersects_[11] = -1; dy0intersects_[11] = 0; dx1intersects_[11] = -1; dy1intersects_[11] = 1;
dx_[12] = -2; dy_[12] = -1;
dx0intersects_[12] = -1; dy0intersects_[12] = 0; dx1intersects_[12] = -1; dy1intersects_[12] = -1;
dx_[13] = -1; dy_[13] = -2;
dx0intersects_[13] = 0; dy0intersects_[13] = -1; dx1intersects_[13] = -1; dy1intersects_[13] = -1;
dx_[14] = 1; dy_[14] = -2;
dx0intersects_[14] = 0; dy0intersects_[14] = -1; dx1intersects_[14] = 1; dy1intersects_[14] = -1;
dx_[15] = 2; dy_[15] = -1;
dx0intersects_[15] = 1; dy0intersects_[15] = 0; dx1intersects_[15] = 1; dy1intersects_[15] = -1;
#endif
//compute distances
for (int dind = 0; dind < SBPL_2DGRIDSEARCH_NUMOF2DDIRS; dind++) {
if (dx_[dind] != 0 && dy_[dind] != 0) {
if (dind <= 7)
//the cost of a diagonal move in millimeters
dxy_distance_mm_[dind] = (int)(cellSize_m_ * 1414);
else
//the cost of a move to 1,2 or 2,1 or so on in millimeters
dxy_distance_mm_[dind] = (int)(cellSize_m_ * 2236);
}
else
dxy_distance_mm_[dind] = (int)(cellSize_m_ * 1000); //the cost of a horizontal move in millimeters
}
}
//--------------------------------------------------------------------------------------------------------------------
//-----------------------------------------debugging functions----------------------------------------------------------
void SBPL2DGridSearch::printvalues()
{
}
//--------------------------------------------------------------------------------------------------------------------
//-----------------------------------------main functions--------------------------------------------------------------
bool SBPL2DGridSearch::search(unsigned char** Grid2D, unsigned char obsthresh, int startx_c, int starty_c, int goalx_c,
int goaly_c, SBPL_2DGRIDSEARCH_TERM_CONDITION termination_condition)
{
startx_c /= downsample_;
starty_c /= downsample_;
goalx_c /= downsample_;
goaly_c /= downsample_;
switch (OPENtype_) {
case SBPL_2DGRIDSEARCH_OPENTYPE_HEAP:
return SBPL2DGridSearch::search_withheap(Grid2D, obsthresh, startx_c, starty_c, goalx_c, goaly_c,
termination_condition);
break;
case SBPL_2DGRIDSEARCH_OPENTYPE_SLIDINGBUCKETS:
return SBPL2DGridSearch::search_withslidingbuckets(Grid2D, obsthresh, startx_c, starty_c, goalx_c, goaly_c,
termination_condition);
break;
default:
std::stringstream ss("ERROR: unknown data structure type = ");
ss << OPENtype_ << " for OPEN2D";
throw SBPL_Exception(ss.str());
};
return false;
}
bool SBPL2DGridSearch::search_withheap(unsigned char** Grid2D, unsigned char obsthresh, int startx_c, int starty_c,
int goalx_c, int goaly_c, SBPL_2DGRIDSEARCH_TERM_CONDITION termination_condition)
{
SBPL_2DGridSearchState *searchExpState = NULL;
SBPL_2DGridSearchState *searchPredState = NULL;
int numofExpands = 0;
int key;
//get the current time
clock_t starttime = clock();
//closed = 0
iteration_++;
//init start and goal coordinates
startX_ = startx_c;
startY_ = starty_c;
goalX_ = goalx_c;
goalY_ = goaly_c;
//clear the heap
OPEN2D_->makeemptyheap();
//set the term. condition
term_condition_usedlast = termination_condition;
//check the validity of start/goal
if (!withinMap(startx_c, starty_c) || !withinMap(goalx_c, goaly_c)) {
SBPL_ERROR("ERROR: grid2Dsearch is called on invalid start (%d %d) or goal(%d %d)\n", startx_c, starty_c,
goalx_c, goaly_c);
return false;
}
// initialize the start and goal states
searchExpState = &searchStates2D_[startX_][startY_];
initializeSearchState2D(searchExpState);
initializeSearchState2D(&searchStates2D_[goalx_c][goaly_c]);
SBPL_2DGridSearchState* search2DGoalState = &searchStates2D_[goalx_c][goaly_c];
//seed the search
searchExpState->g = 0;
key = searchExpState->g;
if (termination_condition == SBPL_2DGRIDSEARCH_TERM_CONDITION_OPTPATHFOUND)
//use h-values only if we are NOT computing all state values
key = key + SBPL_2DGRIDSEARCH_HEUR2D(startX_, startY_);
OPEN2D_->insertheap(searchExpState, key);
//set the termination condition
float term_factor = 0.0;
switch (termination_condition) {
case SBPL_2DGRIDSEARCH_TERM_CONDITION_OPTPATHFOUND:
term_factor = 1;
break;
case SBPL_2DGRIDSEARCH_TERM_CONDITION_20PERCENTOVEROPTPATH:
term_factor = (float)(1.0 / 1.2);
break;
case SBPL_2DGRIDSEARCH_TERM_CONDITION_TWOTIMESOPTPATH:
term_factor = 0.5;
break;
case SBPL_2DGRIDSEARCH_TERM_CONDITION_THREETIMESOPTPATH:
term_factor = (float)(1.0 / 3.0);
break;
case SBPL_2DGRIDSEARCH_TERM_CONDITION_ALLCELLS:
term_factor = 0.0;
break;
default:
SBPL_ERROR("ERROR: incorrect termination factor for grid2Dsearch\n");
term_factor = 0.0;
};
char *pbClosed = (char*)calloc(1, width_ * height_);
//the main repetition of expansions
while (!OPEN2D_->emptyheap() &&
__min(INFINITECOST, search2DGoalState->g) > term_factor * OPEN2D_->getminkeyheap())
{
//get the next state for expansion
searchExpState = (SBPL_2DGridSearchState*)OPEN2D_->deleteminheap();
numofExpands++;
int exp_x = searchExpState->x;
int exp_y = searchExpState->y;
//close the state
pbClosed[exp_x + width_ * exp_y] = 1;
//iterate over successors
int expcost = getCost(Grid2D, exp_x, exp_y, downsample_);
for (int dir = 0; dir < SBPL_2DGRIDSEARCH_NUMOF2DDIRS; dir++) {
int newx = exp_x + dx_[dir];
int newy = exp_y + dy_[dir];
//make sure it is inside the map and has no obstacle
if (!withinMap(newx, newy)) continue;
if (pbClosed[newx + width_ * newy] == 1) continue;
//compute the cost
int mapcost = __max(getCost(Grid2D, newx, newy, downsample_), expcost);
#if SBPL_2DGRIDSEARCH_NUMOF2DDIRS > 8
if(dir > 7) {
//check two more cells through which the action goes
mapcost = __max(mapcost, getCost(Grid2D, exp_x + dx0intersects_[dir], exp_y + dy0intersects_[dir], downsample_));
mapcost = __max(mapcost, getCost(Grid2D, exp_x + dx1intersects_[dir], exp_y + dy1intersects_[dir], downsample_));
}
#endif
if (mapcost >= obsthresh) //obstacle encountered
continue;
int cost = (mapcost + 1) * dxy_distance_mm_[dir];
//get the predecessor
searchPredState = &searchStates2D_[newx][newy];
//update predecessor if necessary
if (searchPredState->iterationaccessed != iteration_ || searchPredState->g > cost + searchExpState->g) {
searchPredState->iterationaccessed = iteration_;
searchPredState->g = __min(INFINITECOST, cost + searchExpState->g);
key = searchPredState->g;
if (termination_condition == SBPL_2DGRIDSEARCH_TERM_CONDITION_OPTPATHFOUND)
//use h-values only if we are NOT computing all state values
key = key + SBPL_2DGRIDSEARCH_HEUR2D(searchPredState->x, searchPredState->y);
if (searchPredState->heapindex == 0)
OPEN2D_->insertheap(searchPredState, key);
else
OPEN2D_->updateheap(searchPredState, key);
}
} //over successors
}//while
//set lower bounds for the remaining states
if (!OPEN2D_->emptyheap())
largestcomputedoptf_ = OPEN2D_->getminkeyheap();
else
largestcomputedoptf_ = INFINITECOST;
free(pbClosed);
SBPL_PRINTF( "# of expands during 2dgridsearch=%d time=%d msecs 2Dsolcost_inmm=%d "
"largestoptfval=%d (start=%d %d goal=%d %d)\n",
numofExpands, (int)(((clock() - starttime) / (double)CLOCKS_PER_SEC) * 1000),
searchStates2D_[goalx_c][goaly_c].g, largestcomputedoptf_, startx_c, starty_c, goalx_c, goaly_c);
return true;
}
//experimental version
//have only one copy of a state in the list, but the order of expansions is
//BFS with possible re-expansions. Thus the order can be maintained by FIFO
//queue implemented by list (requires though the implementation of the lastelement in the list)
bool SBPL2DGridSearch::search_exp(unsigned char** Grid2D, unsigned char obsthresh, int startx_c, int starty_c,
int goalx_c, int goaly_c)
{
SBPL_2DGridSearchState *searchExpState = NULL;
SBPL_2DGridSearchState *searchPredState = NULL;
int numofExpands = 0;
CList OPEN2DLIST;
//get the current time
clock_t starttime = clock();
//closed = 0
iteration_++;
//init start and goal coordinates
startX_ = startx_c;
startY_ = starty_c;
goalX_ = goalx_c;
goalY_ = goaly_c;
//check the validity of start/goal
if (!withinMap(startx_c, starty_c) || !withinMap(goalx_c, goaly_c)) {
SBPL_ERROR("ERROR: grid2Dsearch is called on invalid start (%d %d) or goal(%d %d)\n", startx_c, starty_c,
goalx_c, goaly_c);
return false;
}
// initialize the start and goal states
searchExpState = &searchStates2D_[startX_][startY_];
initializeSearchState2D(searchExpState);
//no initialization for the goal state - it will reset iteration_ variable
//seed the search
searchExpState->g = 0;
searchExpState->listelem[SBPL_2DSEARCH_OPEN_LIST_ID] = NULL;
OPEN2DLIST.insertinfront(searchExpState, SBPL_2DSEARCH_OPEN_LIST_ID);
//the main repetition of expansions
while (!OPEN2DLIST.empty()) {
//get the next state for expansion
searchExpState = (SBPL_2DGridSearchState*)OPEN2DLIST.getlast();
OPEN2DLIST.remove(searchExpState, SBPL_2DSEARCH_OPEN_LIST_ID);
numofExpands++;
int exp_x = searchExpState->x;
int exp_y = searchExpState->y;
//iterate over successors
for (int dir = 0; dir < SBPL_2DGRIDSEARCH_NUMOF2DDIRS; dir++) {
int newx = exp_x + dx_[dir];
int newy = exp_y + dy_[dir];
//make sure it is inside the map and has no obstacle
if (!withinMap(newx, newy)) continue;
//compute the cost
int mapcost = __max( getCost(Grid2D, newx, newy, downsample_), getCost(Grid2D, exp_x, exp_y, downsample_));
#if SBPL_2DGRIDSEARCH_NUMOF2DDIRS > 8
if(dir > 7) {
//check two more cells through which the action goes
mapcost = __max(mapcost, getCost(Grid2D, exp_x + dx0intersects_[dir], exp_y + dy0intersects_[dir], downsample_));
mapcost = __max(mapcost, getCost(Grid2D, exp_x + dx1intersects_[dir], exp_y + dy1intersects_[dir], downsample_));
}
#endif
if (mapcost >= obsthresh) //obstacle encountered
continue;
int cost = (mapcost + 1) * dxy_distance_mm_[dir];
//get the predecessor
searchPredState = &searchStates2D_[newx][newy];
//clear the list
if (searchPredState->iterationaccessed != iteration_) searchPredState->listelem[SBPL_2DSEARCH_OPEN_LIST_ID]
= NULL;
//update predecessor if necessary
if (searchPredState->iterationaccessed != iteration_ || searchPredState->g > cost + searchExpState->g) {
searchPredState->iterationaccessed = iteration_;
searchPredState->g = __min(INFINITECOST, cost + searchExpState->g);
if (searchPredState->g >= INFINITECOST) {
throw SBPL_Exception("ERROR: infinite g");
}
//put it into the list if not there already
if (searchPredState->listelem[SBPL_2DSEARCH_OPEN_LIST_ID] == NULL)
OPEN2DLIST.insertinfront(searchPredState, SBPL_2DSEARCH_OPEN_LIST_ID);
//otherwise, the state remains where it is but it now has a new g-value
}
} //over successors
}//while
//set lower bounds for the remaining states - none left since we exhausted the whole list
largestcomputedoptf_ = INFINITECOST;
SBPL_PRINTF( "# of expands during 2dgridsearch=%d time=%d msecs 2Dsolcost_inmm=%d "
"largestoptfval=%d (start=%d %d goal=%d %d)\n",
numofExpands, (int)(((clock() - starttime) / (double)CLOCKS_PER_SEC) * 1000),
searchStates2D_[goalx_c][goaly_c].g, largestcomputedoptf_, startx_c, starty_c, goalx_c, goaly_c);
return false;
}
//experimental version
//OPEN list is implemented as a bucket list
bool SBPL2DGridSearch::search_withbuckets(unsigned char** Grid2D, unsigned char obsthresh, int startx_c, int starty_c,
int goalx_c, int goaly_c)
{
SBPL_2DGridSearchState *searchExpState = NULL;
SBPL_2DGridSearchState *searchPredState = NULL;
int numofExpands = 0;
//get the current time
clock_t starttime = clock();
//int max_bucketed_priority = obsthresh*10*__max(this->width_, this->height_);
int max_bucketed_priority = (int)(0.1 * obsthresh * dxy_distance_mm_[0] * __max(this->width_, this->height_));
SBPL_PRINTF("bucket-based OPEN2D has up to %d bucketed priorities, the rest will be unsorted\n",
max_bucketed_priority);
CBucket OPEN2DBLIST(0, max_bucketed_priority);
SBPL_PRINTF("OPEN2D allocation time=%d msecs\n", (int)(((clock() - starttime) / (double)CLOCKS_PER_SEC) * 1000));
//closed = 0
iteration_++;
//init start and goal coordinates
startX_ = startx_c;
startY_ = starty_c;
goalX_ = goalx_c;
goalY_ = goaly_c;
//check the validity of start/goal
if (!withinMap(startx_c, starty_c) || !withinMap(goalx_c, goaly_c)) {
SBPL_ERROR("ERROR: grid2Dsearch is called on invalid start (%d %d) or goal(%d %d)\n", startx_c, starty_c,
goalx_c, goaly_c);
return false;
}
// initialize the start and goal states
searchExpState = &searchStates2D_[startX_][startY_];
initializeSearchState2D(searchExpState);
//no initialization for the goal state - it will reset iteration_ variable
//seed the search
searchExpState->g = 0;
searchExpState->heapindex = -1;
OPEN2DBLIST.insert(searchExpState, searchExpState->g);
//the main repetition of expansions
while (!OPEN2DBLIST.empty()) {
//get the next state for expansion
searchExpState = (SBPL_2DGridSearchState*)OPEN2DBLIST.popminelement();
numofExpands++;
int exp_x = searchExpState->x;
int exp_y = searchExpState->y;
//iterate over successors
for (int dir = 0; dir < SBPL_2DGRIDSEARCH_NUMOF2DDIRS; dir++) {
int newx = exp_x + dx_[dir];
int newy = exp_y + dy_[dir];
//make sure it is inside the map and has no obstacle
if (!withinMap(newx, newy)) continue;
//compute the cost
int mapcost = __max( getCost(Grid2D, newx, newy, downsample_), getCost(Grid2D, exp_x, exp_y, downsample_));
#if SBPL_2DGRIDSEARCH_NUMOF2DDIRS > 8
if(dir > 7) {
//check two more cells through which the action goes
mapcost = __max(mapcost, getCost(Grid2D, exp_x + dx0intersects_[dir], exp_y + dy0intersects_[dir], downsample_));
mapcost = __max(mapcost, getCost(Grid2D, exp_x + dx1intersects_[dir], exp_y + dy1intersects_[dir], downsample_));
}
#endif
if (mapcost >= obsthresh) //obstacle encountered
continue;
int cost = (mapcost + 1) * dxy_distance_mm_[dir];
//get the predecessor
searchPredState = &searchStates2D_[newx][newy];
//clear the element from OPEN
if (searchPredState->iterationaccessed != iteration_) searchPredState->heapindex = -1;
//update predecessor if necessary
if (searchPredState->iterationaccessed != iteration_ || searchPredState->g > cost + searchExpState->g) {
int oldstatepriority = searchPredState->g;
searchPredState->iterationaccessed = iteration_;
searchPredState->g = __min(INFINITECOST, cost + searchExpState->g);
if (searchPredState->g >= INFINITECOST) {
throw SBPL_Exception("ERROR: infinite g");
}
//put it into the list if not there already
if (searchPredState->heapindex != -1) OPEN2DBLIST.remove(searchPredState, oldstatepriority);
OPEN2DBLIST.insert(searchPredState, searchPredState->g);
}
} //over successors
}//while
//set lower bounds for the remaining states
if (!OPEN2DBLIST.empty())
largestcomputedoptf_ = OPEN2DBLIST.getminpriority();
else
largestcomputedoptf_ = INFINITECOST;
SBPL_PRINTF( "# of expands during 2dgridsearch=%d time=%d msecs 2Dsolcost_inmm=%d "
"largestoptfval=%d bucketassortedarraymaxsize=%d (start=%d %d goal=%d %d)\n",
numofExpands, (int)(((clock() - starttime) / (double)CLOCKS_PER_SEC) * 1000),
searchStates2D_[goalx_c][goaly_c].g, largestcomputedoptf_, OPEN2DBLIST.maxassortedpriorityVsize,
startx_c, starty_c, goalx_c, goaly_c);
return false;
}
//experimental version
//OPEN list is implemented as a sliding bucket list
bool SBPL2DGridSearch::search_withslidingbuckets(unsigned char** Grid2D, unsigned char obsthresh, int startx_c,
int starty_c, int goalx_c, int goaly_c,
SBPL_2DGRIDSEARCH_TERM_CONDITION termination_condition)
{
SBPL_2DGridSearchState *searchExpState = NULL;
SBPL_2DGridSearchState *searchPredState = NULL;
int numofExpands = 0;
#if DEBUG
#ifndef ROS
const char* f2dgriddebug = "2dgriddebug.txt";
#endif
FILE* f2Dsearch = SBPL_FOPEN(f2dgriddebug, "w");
#endif
//closed = 0
iteration_++;
//init start and goal coordinates
startX_ = startx_c;
startY_ = starty_c;
goalX_ = goalx_c;
goalY_ = goaly_c;
//check the validity of start/goal
if (!withinMap(startx_c, starty_c) || !withinMap(goalx_c, goaly_c)) {
SBPL_ERROR("ERROR: grid2Dsearch is called on invalid start (%d %d) or goal(%d %d)\n", startx_c, starty_c,
goalx_c, goaly_c);
#if DEBUG
SBPL_FCLOSE(f2Dsearch);
#endif
return false;
}
//reset OPEN
OPEN2DBLIST_->reset();
//set the term. condition
term_condition_usedlast = termination_condition;
// initialize the start and goal states
searchExpState = &searchStates2D_[startX_][startY_];
initializeSearchState2D(searchExpState);
initializeSearchState2D(&searchStates2D_[goalx_c][goaly_c]);
SBPL_2DGridSearchState* search2DGoalState = &searchStates2D_[goalx_c][goaly_c];
//seed the search
searchExpState->g = 0;
OPEN2DBLIST_->insert(searchExpState, searchExpState->g);
//set the termination condition
float term_factor = 0.0;
switch (termination_condition) {
case SBPL_2DGRIDSEARCH_TERM_CONDITION_OPTPATHFOUND:
term_factor = 1;
break;
case SBPL_2DGRIDSEARCH_TERM_CONDITION_20PERCENTOVEROPTPATH:
term_factor = (float)(1.0 / 1.2);
break;
case SBPL_2DGRIDSEARCH_TERM_CONDITION_TWOTIMESOPTPATH:
term_factor = 0.5;
break;
case SBPL_2DGRIDSEARCH_TERM_CONDITION_THREETIMESOPTPATH:
term_factor = (float)(1.0 / 3.0);
break;
case SBPL_2DGRIDSEARCH_TERM_CONDITION_ALLCELLS:
term_factor = 0.0;
break;
default:
SBPL_ERROR("ERROR: incorrect termination factor for grid2Dsearch\n");
term_factor = 0.0;
};
//get the current time
clock_t starttime = clock();
char *pbClosed = (char*)calloc(1, width_ * height_);
//the main repetition of expansions
SBPL_PRINTF("2D search with sliding buckets and term_factor=%.3f\n", term_factor);
int prevg = 0;
while (!OPEN2DBLIST_->empty() && search2DGoalState->g > term_factor * OPEN2DBLIST_->getminkey()) {
#if DEBUG
SBPL_FPRINTF(f2Dsearch, "currentminelement_priority before pop=%d\n", OPEN2DBLIST_->getminkey());
#endif
//get the next state for expansion
searchExpState = (SBPL_2DGridSearchState*)OPEN2DBLIST_->popminelement();
if (searchExpState->g > OPEN2DBLIST_->getminkey()) {
SBPL_ERROR("ERROR: g=%d for state %d %d but minpriority=%d (prevg=%d)\n", searchExpState->g,
searchExpState->x, searchExpState->y, OPEN2DBLIST_->getminkey(), prevg);
}
prevg = searchExpState->g;
int exp_x = searchExpState->x;
int exp_y = searchExpState->y;
//close the state if it wasn't yet
if (pbClosed[exp_x + width_ * exp_y] == 1) continue;
pbClosed[exp_x + width_ * exp_y] = 1;
#if DEBUG
SBPL_FPRINTF(f2Dsearch, "expanding state <%d %d> with g=%d "
"(currentminelement_priority=%d, currentfirstbucket_bindex=%d, currentfirstbucket_priority=%d)\n",
searchExpState->x, searchExpState->y, searchExpState->g, OPEN2DBLIST_->getminkey(),
OPEN2DBLIST_->currentfirstbucket_bindex, OPEN2DBLIST_->currentfirstbucket_priority);
#endif
//expand
numofExpands++;
//iterate over successors
int expcost = getCost(Grid2D, exp_x, exp_y, downsample_);
for (int dir = 0; dir < SBPL_2DGRIDSEARCH_NUMOF2DDIRS; dir++) {
int newx = exp_x + dx_[dir];
int newy = exp_y + dy_[dir];
//make sure it is inside the map and has no obstacle
if (!withinMap(newx, newy)) continue;
if (pbClosed[newx + width_ * newy] == 1) continue;
//compute the cost
int mapcost = __max( getCost(Grid2D, newx, newy, downsample_), expcost);
#if SBPL_2DGRIDSEARCH_NUMOF2DDIRS > 8
if(dir > 7) {
//check two more cells through which the action goes
mapcost = __max(mapcost, getCost(Grid2D, exp_x + dx0intersects_[dir], exp_y + dy0intersects_[dir], downsample_));
mapcost = __max(mapcost, getCost(Grid2D, exp_x + dx1intersects_[dir], exp_y + dy1intersects_[dir], downsample_));
}
#endif
if (mapcost >= obsthresh) //obstacle encountered
continue;
int cost = (mapcost + 1) * dxy_distance_mm_[dir];
//get the predecessor
searchPredState = &searchStates2D_[newx][newy];
//update predecessor if necessary
if (searchPredState->iterationaccessed != iteration_ || searchPredState->g > cost + searchExpState->g) {
searchPredState->iterationaccessed = iteration_;
searchPredState->g = __min(INFINITECOST, cost + searchExpState->g);
#if DEBUG
SBPL_FPRINTF(f2Dsearch, "inserting state <%d %d> with g=%d\n", searchPredState->x, searchPredState->y, searchPredState->g);
#endif
//put it into the list
OPEN2DBLIST_->insert(searchPredState, searchPredState->g);
}
} //over successors
}//while
//set lower bounds for the remaining states
if (!OPEN2DBLIST_->empty())
largestcomputedoptf_ = ((SBPL_2DGridSearchState*)OPEN2DBLIST_->getminelement())->g;
else
largestcomputedoptf_ = INFINITECOST;
//delete[] pbClosed;
free(pbClosed);
SBPL_PRINTF( "# of expands during 2dgridsearch=%d time=%d msecs 2Dsolcost_inmm=%d "
"largestoptfval=%d (start=%d %d goal=%d %d)\n",
numofExpands, (int)(((clock() - starttime) / (double)CLOCKS_PER_SEC) * 1000),
searchStates2D_[goalx_c][goaly_c].g, largestcomputedoptf_, startx_c, starty_c, goalx_c, goaly_c);
#if DEBUG
SBPL_FCLOSE(f2Dsearch);
#endif
return true;
}
//----------------------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sbpl/config.h>
#include <cstdarg>
#include <cstdlib>
#include <cstring>
#define SBPL_PRINTF_BUFFER_SIZE 1024
static int SBPL_DEFAULT_DEBUG_OUTPUT_LOGGER(int, const char*);
static int SBPL_DEFAULT_DEBUG_OUTPUT_FLUSH(FILE*);
// set appropriate default logger
#if DEBUG && !defined(ROS)
static SBPL_PRINT_TEXT_FP sbpl_print_fp = SBPL_DEFAULT_DEBUG_OUTPUT_LOGGER;
static SBPL_FFLUSH_TEXT_FP sbpl_fflush_fp = SBPL_DEFAULT_DEBUG_OUTPUT_FLUSH;
#else
static SBPL_PRINT_TEXT_FP sbpl_print_fp = NULL;
static SBPL_FFLUSH_TEXT_FP sbpl_fflush_fp = NULL;
#endif
void SET_SBPL_PRINT_TEXT_FP(SBPL_PRINT_TEXT_FP fptr) { sbpl_print_fp = fptr; }
void SET_SBPL_FFLUSH_TEXT_FP(SBPL_FFLUSH_TEXT_FP fptr) { sbpl_fflush_fp = fptr; }
int SBPL_PRINTALL(int level, const char* format, ...)
{
int retVal = 0;
if (sbpl_print_fp) {
// parse arguments and pass resultant string to configured logger
va_list args;
va_start(args, format);
char buffer[SBPL_PRINTF_BUFFER_SIZE] = {0};
retVal = vsnprintf(buffer,SBPL_PRINTF_BUFFER_SIZE - 1, format, args);
if (retVal < 0) {
printf("SBPL_PRINTALL::ERROR, could not complete call to vsnprintf()");
}
else {
if (retVal == SBPL_PRINTF_BUFFER_SIZE) {
printf("SBPL_PRINTALL::ERROR, SBPL_PRINTF_BUFFER_SIZE: %d not large enough", SBPL_PRINTF_BUFFER_SIZE);
}
if(buffer[retVal-1] == '\n') { // Remove newline
buffer[retVal-1] = '\0';
}
sbpl_print_fp(level, &buffer[0]);
}
va_end(args);
}
return retVal;
}
int SBPL_FPRINTALL(FILE* file, const char* format, ...)
{
int retVal = 0;
va_list args;
va_start(args, format);
if ((file == stdout) && (sbpl_print_fp != NULL)) {
char buffer[SBPL_PRINTF_BUFFER_SIZE] = {0};
retVal = vsnprintf(buffer,SBPL_PRINTF_BUFFER_SIZE-1,format, args);
if (retVal < 0) {
printf("SBPL_PRINTALL::ERROR, could not complete call to vsnprintf()");
}
else {
if (retVal == SBPL_PRINTF_BUFFER_SIZE) {
printf("SBPL_PRINTALL::ERROR, SBPL_PRINTF_BUFFER_SIZE: %d not large enough", SBPL_PRINTF_BUFFER_SIZE);
}
if(buffer[retVal-1] == '\n') { // Remove newline
buffer[retVal-1] = '\0';
}
sbpl_print_fp(SBPL_LEVEL_NONE, &buffer[0]);
}
}
else {
retVal = vfprintf(file, format, args);
}
va_end (args);
return retVal;
}
int SBPL_FFLUSHALL(FILE* file)
{
int retVal = 0;
if (sbpl_fflush_fp) {
retVal = sbpl_fflush_fp(file);
}
return retVal;
}
int SBPL_DEFAULT_DEBUG_OUTPUT_LOGGER(int level, const char* msg)
{
switch (level)
{
case SBPL_LEVEL_NONE:
case SBPL_LEVEL_DEBUG:
case SBPL_LEVEL_INFO:
case SBPL_LEVEL_WARN:
return printf("%s\n", msg);
case SBPL_LEVEL_ERROR:
case SBPL_LEVEL_FATAL:
return fprintf(stderr, "%s\n", msg);
default:
return -1;
}
}
int SBPL_DEFAULT_DEBUG_OUTPUT_FLUSH(FILE* f)
{
return fflush(f);
}

View File

@@ -0,0 +1,514 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sbpl/sbpl_exception.h>
#include <sbpl/utils/heap.h>
using namespace std;
void heaperror(const char* ErrorString)
{
//need to send a message from here somehow
throw SBPL_Exception(ErrorString);
}
//returns an infinite key
CKey InfiniteKey()
{
CKey key;
key.SetKeytoInfinity();
return key;
}
//---------------------------------normal (multi-priority) CHeap class--------------------------------------------------
//constructors and destructors
CHeap::CHeap()
{
percolates = 0;
currentsize = 0;
allocated = HEAPSIZE_INIT;
heap = new heapelement[allocated];
}
CHeap::~CHeap()
{
int i;
for (i = 1; i <= currentsize; ++i)
heap[i].heapstate->heapindex = 0;
delete[] heap;
}
void CHeap::percolatedown(int hole, heapelement tmp)
{
int child;
if (currentsize != 0) {
for (; 2 * hole <= currentsize; hole = child) {
child = 2 * hole;
if (child != currentsize && heap[child + 1].key < heap[child].key) ++child;
if (heap[child].key < tmp.key) {
percolates += 1;
heap[hole] = heap[child];
heap[hole].heapstate->heapindex = hole;
}
else
break;
}
heap[hole] = tmp;
heap[hole].heapstate->heapindex = hole;
}
}
void CHeap::percolateup(int hole, heapelement tmp)
{
if (currentsize != 0) {
for (; hole > 1 && tmp.key < heap[hole / 2].key; hole /= 2) {
percolates += 1;
heap[hole] = heap[hole / 2];
heap[hole].heapstate->heapindex = hole;
}
heap[hole] = tmp;
heap[hole].heapstate->heapindex = hole;
}
}
void CHeap::percolateupordown(int hole, heapelement tmp)
{
if (currentsize != 0) {
if (hole > 1 && heap[hole / 2].key > tmp.key)
percolateup(hole, tmp);
else
percolatedown(hole, tmp);
}
}
bool CHeap::emptyheap()
{
return currentsize == 0;
}
bool CHeap::fullheap()
{
return currentsize == HEAPSIZE - 1;
}
bool CHeap::inheap(AbstractSearchState *AbstractSearchState)
{
return (AbstractSearchState->heapindex != 0);
}
CKey CHeap::getkeyheap(AbstractSearchState *AbstractSearchState)
{
if (AbstractSearchState->heapindex == 0) heaperror("GetKey: AbstractSearchState is not in heap");
return heap[AbstractSearchState->heapindex].key;
}
void CHeap::makeemptyheap()
{
int i;
for (i = 1; i <= currentsize; ++i)
heap[i].heapstate->heapindex = 0;
currentsize = 0;
}
void CHeap::makeheap()
{
int i;
for (i = currentsize / 2; i > 0; i--) {
percolatedown(i, heap[i]);
}
}
void CHeap::growheap()
{
heapelement* newheap;
int i;
SBPL_PRINTF("growing heap size from %d ", allocated);
allocated = 2 * allocated;
if (allocated > HEAPSIZE) allocated = HEAPSIZE;
SBPL_PRINTF("to %d\n", allocated);
newheap = new heapelement[allocated];
for (i = 0; i <= currentsize; ++i)
newheap[i] = heap[i];
delete[] heap;
heap = newheap;
}
void CHeap::sizecheck()
{
if (fullheap())
heaperror("insertheap: heap is full");
else if (currentsize == allocated - 1) {
growheap();
}
}
void CHeap::insertheap(AbstractSearchState *AbstractSearchState, CKey key)
{
heapelement tmp;
char strTemp[100];
sizecheck();
if (AbstractSearchState->heapindex != 0) {
sprintf(strTemp, "insertheap: AbstractSearchState is already in heap");
heaperror(strTemp);
}
tmp.heapstate = AbstractSearchState;
tmp.key = key;
percolateup(++currentsize, tmp);
}
void CHeap::deleteheap(AbstractSearchState *AbstractSearchState)
{
if (AbstractSearchState->heapindex == 0) heaperror("deleteheap: AbstractSearchState is not in heap");
percolateupordown(AbstractSearchState->heapindex, heap[currentsize--]);
AbstractSearchState->heapindex = 0;
}
void CHeap::updateheap(AbstractSearchState *AbstractSearchState, CKey NewKey)
{
if (AbstractSearchState->heapindex == 0) heaperror("Updateheap: AbstractSearchState is not in heap");
if (heap[AbstractSearchState->heapindex].key != NewKey) {
heap[AbstractSearchState->heapindex].key = NewKey;
percolateupordown(AbstractSearchState->heapindex, heap[AbstractSearchState->heapindex]);
}
}
void CHeap::insert_unsafe(AbstractSearchState* AbstractSearchState, CKey key)
{
heapelement tmp;
char strTemp[100];
sizecheck();
if (AbstractSearchState->heapindex != 0) {
sprintf(strTemp, "insertheap: AbstractSearchState is already in heap");
heaperror(strTemp);
}
tmp.heapstate = AbstractSearchState;
tmp.key = key;
++currentsize;
heap[currentsize] = tmp;
heap[currentsize].heapstate->heapindex = currentsize;
}
void CHeap::deleteheap_unsafe(AbstractSearchState* AbstractSearchState)
{
if (AbstractSearchState->heapindex == 0) {
heaperror("deleteheap: AbstractSearchState is not in heap");
}
heap[AbstractSearchState->heapindex] = heap[currentsize];
--currentsize;
heap[AbstractSearchState->heapindex].heapstate->heapindex = AbstractSearchState->heapindex;
AbstractSearchState->heapindex = 0;
}
void CHeap::updateheap_unsafe(AbstractSearchState* AbstractSearchState, CKey NewKey)
{
if (AbstractSearchState->heapindex == 0) {
heaperror("updateheap: AbstractSearchState is not in heap");
}
if (heap[AbstractSearchState->heapindex].key != NewKey) {
heap[AbstractSearchState->heapindex].key = NewKey;
}
}
AbstractSearchState* CHeap::getminheap()
{
if (currentsize == 0) heaperror("GetMinheap: heap is empty");
return heap[1].heapstate;
}
AbstractSearchState* CHeap::getminheap(CKey& ReturnKey)
{
if (currentsize == 0) {
heaperror("GetMinheap: heap is empty");
ReturnKey = InfiniteKey();
}
ReturnKey = heap[1].key;
return heap[1].heapstate;
}
CKey CHeap::getminkeyheap()
{
CKey ReturnKey;
if (currentsize == 0) return InfiniteKey();
ReturnKey = heap[1].key;
return ReturnKey;
}
AbstractSearchState* CHeap::deleteminheap()
{
AbstractSearchState *AbstractSearchState;
if (currentsize == 0) heaperror("DeleteMin: heap is empty");
AbstractSearchState = heap[1].heapstate;
AbstractSearchState->heapindex = 0;
percolatedown(1, heap[currentsize--]);
return AbstractSearchState;
}
//---------------------------------end of normal (multi-priority) CHeap class-------------------------------------------
//---------------------------------single-priority CIntHeap class---------------------------------------------------
//constructors and destructors
CIntHeap::CIntHeap()
{
percolates = 0;
currentsize = 0;
allocated = HEAPSIZE_INIT;
heap = new heapintelement[allocated];
}
CIntHeap::CIntHeap(int initial_size)
{
percolates = 0;
currentsize = 0;
allocated = initial_size;
heap = new heapintelement[allocated];
}
CIntHeap::~CIntHeap()
{
int i;
for (i = 1; i <= currentsize; ++i)
heap[i].heapstate->heapindex = 0;
delete[] heap;
}
void CIntHeap::percolatedown(int hole, heapintelement tmp)
{
int child;
if (currentsize != 0) {
for (; 2 * hole <= currentsize; hole = child) {
child = 2 * hole;
if (child != currentsize && heap[child + 1].key < heap[child].key) ++child;
if (heap[child].key < tmp.key) {
percolates += 1;
heap[hole] = heap[child];
heap[hole].heapstate->heapindex = hole;
}
else
break;
}
heap[hole] = tmp;
heap[hole].heapstate->heapindex = hole;
}
}
void CIntHeap::percolateup(int hole, heapintelement tmp)
{
if (currentsize != 0) {
for (; hole > 1 && tmp.key < heap[hole / 2].key; hole /= 2) {
percolates += 1;
heap[hole] = heap[hole / 2];
heap[hole].heapstate->heapindex = hole;
}
heap[hole] = tmp;
heap[hole].heapstate->heapindex = hole;
}
}
void CIntHeap::percolateupordown(int hole, heapintelement tmp)
{
if (currentsize != 0) {
if (hole > 1 && heap[hole / 2].key > tmp.key)
percolateup(hole, tmp);
else
percolatedown(hole, tmp);
}
}
bool CIntHeap::emptyheap()
{
return currentsize == 0;
}
bool CIntHeap::fullheap()
{
return currentsize == HEAPSIZE - 1;
}
bool CIntHeap::inheap(AbstractSearchState *AbstractSearchState)
{
return (AbstractSearchState->heapindex != 0);
}
int CIntHeap::getkeyheap(AbstractSearchState *AbstractSearchState)
{
if (AbstractSearchState->heapindex == 0) heaperror("GetKey: AbstractSearchState is not in heap");
return heap[AbstractSearchState->heapindex].key;
}
void CIntHeap::makeemptyheap()
{
int i;
for (i = 1; i <= currentsize; ++i)
heap[i].heapstate->heapindex = 0;
currentsize = 0;
}
void CIntHeap::makeheap()
{
int i;
for (i = currentsize / 2; i > 0; i--) {
percolatedown(i, heap[i]);
}
}
void CIntHeap::growheap()
{
heapintelement* newheap;
int i;
SBPL_PRINTF("growing heap size from %d ", allocated);
allocated = 2 * allocated;
if (allocated > HEAPSIZE) allocated = HEAPSIZE;
SBPL_PRINTF("to %d\n", allocated);
newheap = new heapintelement[allocated];
for (i = 0; i <= currentsize; ++i)
newheap[i] = heap[i];
delete[] heap;
heap = newheap;
}
void CIntHeap::sizecheck()
{
if (fullheap())
heaperror("insertheap: heap is full");
else if (currentsize == allocated - 1) {
growheap();
}
}
void CIntHeap::insertheap(AbstractSearchState *AbstractSearchState, int key)
{
heapintelement tmp;
char strTemp[100];
sizecheck();
if (AbstractSearchState->heapindex != 0) {
sprintf(strTemp, "insertheap: AbstractSearchState is already in heap");
heaperror(strTemp);
}
tmp.heapstate = AbstractSearchState;
tmp.key = key;
percolateup(++currentsize, tmp);
}
void CIntHeap::deleteheap(AbstractSearchState *AbstractSearchState)
{
if (AbstractSearchState->heapindex == 0) heaperror("deleteheap: AbstractSearchState is not in heap");
percolateupordown(AbstractSearchState->heapindex, heap[currentsize--]);
AbstractSearchState->heapindex = 0;
}
void CIntHeap::updateheap(AbstractSearchState *AbstractSearchState, int NewKey)
{
if (AbstractSearchState->heapindex == 0) heaperror("Updateheap: AbstractSearchState is not in heap");
if (heap[AbstractSearchState->heapindex].key != NewKey) {
heap[AbstractSearchState->heapindex].key = NewKey;
percolateupordown(AbstractSearchState->heapindex, heap[AbstractSearchState->heapindex]);
}
}
AbstractSearchState* CIntHeap::getminheap()
{
if (currentsize == 0) heaperror("GetMinheap: heap is empty");
return heap[1].heapstate;
}
AbstractSearchState* CIntHeap::getminheap(int& ReturnKey)
{
if (currentsize == 0) {
heaperror("GetMinheap: heap is empty");
}
ReturnKey = heap[1].key;
return heap[1].heapstate;
}
int CIntHeap::getminkeyheap()
{
int ReturnKey;
if (currentsize == 0) return INFINITECOST;
ReturnKey = heap[1].key;
return ReturnKey;
}
AbstractSearchState* CIntHeap::deleteminheap()
{
AbstractSearchState *AbstractSearchState;
if (currentsize == 0) heaperror("DeleteMin: heap is empty");
AbstractSearchState = heap[1].heapstate;
AbstractSearchState->heapindex = 0;
percolatedown(1, heap[currentsize--]);
return AbstractSearchState;
}
//---------------------------------end of single-priority CIntHeap class------------------------------------------------

View File

@@ -0,0 +1,324 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
//MDP.cpp - contains all the functions for MDP classes
#include <cmath>
#include <sbpl/utils/mdp.h>
#include <sbpl/utils/utils.h>
using namespace std;
//-------------------------MDPACTION class functions----------
bool CMDPACTION::Delete()
{
SuccsID.clear();
Costs.clear();
SuccsProb.clear();
return true;
}
bool CMDPACTION::DeleteAllOutcomes()
{
SuccsID.clear();
Costs.clear();
SuccsProb.clear();
return true;
}
bool CMDPACTION::IsValid()
{
float Prob = 0;
for (int i = 0; i < (int)SuccsProb.size(); i++) {
Prob += SuccsProb[i];
}
return (fabs(Prob - 1.0) < EPS_ERROR);
}
void CMDPACTION::AddOutcome(int OutcomeStateID, int OutcomeCost, float OutcomeProb)
{
#if MEM_CHECK
DisableMemCheck();
#endif
SuccsID.push_back(OutcomeStateID);
Costs.push_back(OutcomeCost);
SuccsProb.push_back(OutcomeProb);
#if MEM_CHECK
EnableMemCheck();
#endif
}
void CMDPACTION::operator =(const CMDPACTION& rhsaction)
{
this->ActionID = rhsaction.ActionID;
}
int CMDPACTION::GetIndofMostLikelyOutcome()
{
double HighestProb = 0;
int mlind = -1;
for (int oind = 0; oind < (int)this->SuccsID.size(); oind++) {
if (this->SuccsProb[oind] >= HighestProb) {
mlind = oind;
HighestProb = this->SuccsProb[oind];
}
}
return mlind;
}
int CMDPACTION::GetIndofOutcome(int OutcomeID)
{
for (int oind = 0; oind < (int)this->SuccsID.size(); oind++) {
if (this->SuccsID[oind] == OutcomeID) {
return oind;
}
}
return -1;
}
//----------------------------------------------------------------------
//----------------------------MDPSTATE class functions---------------
bool CMDPSTATE::Delete()
{
CMDPACTION* action;
if (this->PlannerSpecificData != NULL) {
throw SBPL_Exception("ERROR deleting state: planner specific data is not deleted");
}
//delete predecessors array
PredsID.clear();
//delete actions array
while ((int)Actions.size() > 0) {
action = Actions[Actions.size() - 1];
Actions.pop_back();
action->Delete();
delete action;
}
return true;
}
CMDPACTION* CMDPSTATE::AddAction(int ID)
{
CMDPACTION* action = new CMDPACTION(ID, this->StateID);
#if MEM_CHECK
DisableMemCheck();
#endif
Actions.push_back(action);
#if MEM_CHECK
EnableMemCheck();
#endif
return action;
}
bool CMDPSTATE::AddPred(int stateID)
{
//add the predecessor
if (!ContainsPred(stateID)) {
#if MEM_CHECK
DisableMemCheck();
#endif
PredsID.push_back(stateID);
#if MEM_CHECK
EnableMemCheck();
#endif
}
return true;
}
bool CMDPSTATE::RemovePred(int stateID)
{
for (int i = 0; i < (int)this->PredsID.size(); i++) {
if (this->PredsID.at(i) == stateID) {
this->PredsID.at(i) = this->PredsID.at(this->PredsID.size() - 1);
this->PredsID.pop_back();
return true;
}
}
//can happen when a state is twice a successor
//throw SBPL_Exception("ERROR in RemovePRed: no Pred is found");
return false;
}
//requires the deletion of Preds elsewhere
bool CMDPSTATE::RemoveAllActions()
{
CMDPACTION* action;
//delete actions array
while ((int)Actions.size() > 0) {
action = Actions[Actions.size() - 1];
Actions.pop_back();
action->Delete();
delete action;
}
return true;
}
bool CMDPSTATE::ContainsPred(int stateID)
{
for (int i = 0; i < (int)PredsID.size(); i++) {
if (PredsID[i] == stateID) return true;
}
return false;
}
void CMDPSTATE::operator =(const CMDPSTATE& rhsstate)
{
this->StateID = rhsstate.StateID;
}
CMDPACTION* CMDPSTATE::GetAction(int actionID)
{
for (int i = 0; i < (int)Actions.size(); i++) {
if (Actions[i]->ActionID == actionID) return Actions[i];
}
return NULL;
}
//-------------------------------------------------------------------------
//-------------MDP class functions--------------------------------
bool CMDP::empty()
{
return ((int)StateArray.size() == 0);
}
bool CMDP::full()
{
return ((int)StateArray.size() >= MAXSTATESPACESIZE);
}
//creates numofstates states. Their ids must be initialized elsewhere
bool CMDP::Create(int numofstates)
{
CMDPSTATE* state;
if (numofstates > MAXSTATESPACESIZE) {
throw SBPL_Exception("ERROR in Create: maximum MDP size is reached");
}
for (int i = 0; i < numofstates; i++) {
state = new CMDPSTATE(-1);
#if MEM_CHECK
DisableMemCheck();
#endif
StateArray.push_back(state);
#if MEM_CHECK
EnableMemCheck();
#endif
}
return true;
}
//Adds a new state The id must be initialized elsewhere
CMDPSTATE* CMDP::AddState(int StateID)
{
CMDPSTATE* state;
if ((int)StateArray.size() + 1 > MAXSTATESPACESIZE) {
throw SBPL_Exception("ERROR: maximum of states is reached in MDP");
}
state = new CMDPSTATE(StateID);
#if MEM_CHECK
DisableMemCheck();
#endif
StateArray.push_back(state);
#if MEM_CHECK
EnableMemCheck();
#endif
return state;
}
bool CMDP::Delete()
{
CMDPSTATE* state;
while ((int)StateArray.size() > 0) {
state = StateArray[StateArray.size() - 1];
StateArray.pop_back();
state->Delete();
delete state;
}
return true;
}
void CMDP::Print(FILE* fOut)
{
SBPL_FPRINTF(fOut, "MDP statespace size=%d\n", (unsigned int)StateArray.size());
for (int i = 0; i < (int)StateArray.size(); i++) {
SBPL_FPRINTF(fOut, "%d: ", StateArray[i]->StateID);
for (int j = 0; j < (int)StateArray[i]->Actions.size(); j++) {
CMDPACTION* action = StateArray[i]->Actions[j];
SBPL_FPRINTF(fOut, "[%d", action->ActionID);
for (int outind = 0; outind < (int)action->SuccsID.size(); outind++) {
SBPL_FPRINTF(fOut, " %d %d %f", action->SuccsID[outind], action->Costs[outind],
action->SuccsProb[outind]);
}
SBPL_FPRINTF(fOut, "] ");
}
SBPL_FPRINTF(fOut, "\n");
}
}
//--------------------------------------------------------
//----------------other functions-------------------------

View File

@@ -0,0 +1,929 @@
/*
* Copyright (c) 2008, Maxim Likhachev
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Carnegie Mellon University nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <cmath>
#include <cstdlib>
#include <sstream>
#include <sbpl/planners/planner.h>
#include <sbpl/utils/utils.h>
#include <sbpl/utils/key.h>
#include <sbpl/utils/mdp.h>
#include <sbpl/utils/sbpl_bfs_2d.h>
using namespace std;
#if MEM_CHECK == 1
void DisableMemCheck()
{
// Get the current state of the flag
// and store it in a temporary variable
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
// Turn On (OR) - All freed memory is re-initialized with xDD
tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
// Turn Off (AND) - memory checking is disabled for future allocations
tmpFlag &= ~_CRTDBG_ALLOC_MEM_DF;
// Set the new state for the flag
_CrtSetDbgFlag( tmpFlag );
}
void EnableMemCheck()
{
// Get the current state of the flag
// and store it in a temporary variable
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
// Turn On (OR) - All freed memory is re-initialized with xDD
tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
// Turn On (OR) - memory checking is enabled for future allocations
tmpFlag |= _CRTDBG_ALLOC_MEM_DF;
// Set the new state for the flag
_CrtSetDbgFlag( tmpFlag );
}
#endif
void checkmdpstate(CMDPSTATE* state)
{
#if DEBUG == 0
throw SBPL_Exception("ERROR: checkMDPstate is too expensive for not in DEBUG mode");
#endif
for (int aind = 0; aind < (int)state->Actions.size(); aind++) {
for (int aind1 = 0; aind1 < (int)state->Actions.size(); aind1++) {
if (state->Actions[aind1]->ActionID == state->Actions[aind]->ActionID && aind1 != aind) {
throw SBPL_Exception("ERROR in CheckMDP: multiple actions with the same ID exist");
}
}
for (int sind = 0; sind < (int)state->Actions[aind]->SuccsID.size(); sind++) {
for (int sind1 = 0; sind1 < (int)state->Actions[aind]->SuccsID.size(); sind1++) {
if (state->Actions[aind]->SuccsID[sind] == state->Actions[aind]->SuccsID[sind1] && sind != sind1) {
throw SBPL_Exception("ERROR in CheckMDP: multiple outcomes with the same ID exist");
}
}
}
}
}
void CheckMDP(CMDP* mdp)
{
for (int i = 0; i < (int)mdp->StateArray.size(); i++) {
checkmdpstate(mdp->StateArray[i]);
}
}
void PrintMatrix(int** matrix, int rows, int cols, FILE* fOut)
{
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
SBPL_FPRINTF(fOut, "%d ", matrix[r][c]);
}
SBPL_FPRINTF(fOut, "\n");
}
}
//return true if there exists a path from sourcestate to targetstate and false otherwise
bool PathExists(CMDP* pMarkovChain, CMDPSTATE* sourcestate, CMDPSTATE* targetstate)
{
CMDPSTATE* state;
vector<CMDPSTATE*> WorkList;
int i;
bool *bProcessed = new bool[pMarkovChain->StateArray.size()];
bool bFound = false;
for (i = 0; i < (int)pMarkovChain->StateArray.size(); i++)
{
bProcessed[i] = false;
}
//insert the source state
WorkList.push_back(sourcestate);
while ((int)WorkList.size() > 0) {
//get the state and its info
state = WorkList[WorkList.size() - 1];
WorkList.pop_back();
//Markov Chain should just contain a single policy
if ((int)state->Actions.size() > 1) {
throw SBPL_Exception("ERROR in PathExists: Markov Chain is a general MDP");
}
if (state == targetstate) {
//path found
bFound = true;
break;
}
//otherwise just insert policy successors into the worklist unless it is a goal state
for (int sind = 0; (int)state->Actions.size() != 0 && sind < (int)state->Actions[0]->SuccsID.size(); sind++) {
//get a successor
for (i = 0; i < (int)pMarkovChain->StateArray.size(); i++) {
if (pMarkovChain->StateArray[i]->StateID == state->Actions[0]->SuccsID[sind]) break;
}
if (i == (int)pMarkovChain->StateArray.size()) {
throw SBPL_Exception("ERROR in PathExists: successor is not found");
}
CMDPSTATE* SuccState = pMarkovChain->StateArray[i];
//insert at the end of list if not there or processed already
if (!bProcessed[i]) {
bProcessed[i] = true;
WorkList.push_back(SuccState);
}
} //for successors
}//while WorkList is non empty
delete[] bProcessed;
return bFound;
}
int ComputeNumofStochasticActions(CMDP* pMDP)
{
int i;
int nNumofStochActions = 0;
SBPL_PRINTF("ComputeNumofStochasticActions...\n");
for (i = 0; i < (int)pMDP->StateArray.size(); i++) {
for (int aind = 0; aind < (int)pMDP->StateArray[i]->Actions.size(); aind++) {
if ((int)pMDP->StateArray[i]->Actions[aind]->SuccsID.size() > 1) nNumofStochActions++;
}
}
SBPL_PRINTF("done\n");
return nNumofStochActions;
}
void EvaluatePolicy(CMDP* PolicyMDP, int StartStateID, int GoalStateID, double* PolValue, bool *bFullPolicy,
double* Pcgoal, int *nMerges, bool* bCycles)
{
int i, j, startind = -1;
double delta = INFINITECOST;
double mindelta = 0.1;
*Pcgoal = 0;
*nMerges = 0;
SBPL_PRINTF("Evaluating policy...\n");
//create and initialize values
double* vals = new double[PolicyMDP->StateArray.size()];
double* Pcvals = new double[PolicyMDP->StateArray.size()];
for (i = 0; i < (int)PolicyMDP->StateArray.size(); i++) {
vals[i] = 0;
Pcvals[i] = 0;
//remember the start index
if (PolicyMDP->StateArray[i]->StateID == StartStateID) {
startind = i;
Pcvals[i] = 1;
}
}
//initially assume full policy
*bFullPolicy = true;
bool bFirstIter = true;
while (delta > mindelta) {
delta = 0;
for (i = 0; i < (int)PolicyMDP->StateArray.size(); i++) {
//get the state
CMDPSTATE* state = PolicyMDP->StateArray[i];
//do the backup for values
if (state->StateID == GoalStateID) {
vals[i] = 0;
}
else if ((int)state->Actions.size() == 0) {
*bFullPolicy = false;
vals[i] = UNKNOWN_COST;
*PolValue = vals[startind];
return;
}
else {
//normal backup
CMDPACTION* action = state->Actions[0];
//do backup
double Q = 0;
for (int oind = 0; oind < (int)action->SuccsID.size(); oind++) {
//get the state
for (j = 0; j < (int)PolicyMDP->StateArray.size(); j++) {
if (PolicyMDP->StateArray[j]->StateID == action->SuccsID[oind]) break;
}
if (j == (int)PolicyMDP->StateArray.size()) {
std::stringstream ss("ERROR in EvaluatePolicy: incorrect successor ");
ss << action->SuccsID[oind];
throw SBPL_Exception(ss.str());
}
Q += action->SuccsProb[oind] * (vals[j] + action->Costs[oind]);
}
if (vals[i] > Q) {
throw SBPL_Exception("ERROR in EvaluatePolicy: val is decreasing");
}
//update delta
if (delta < Q - vals[i]) delta = Q - vals[i];
//set the value
vals[i] = Q;
}
//iterate through all the predecessors and compute Pc
double Pc = 0;
//go over all predecessor states
int nMerge = 0;
for (j = 0; j < (int)PolicyMDP->StateArray.size(); j++) {
for (int oind = 0; (int)PolicyMDP->StateArray[j]->Actions.size() > 0 &&
oind < (int)PolicyMDP->StateArray[j]->Actions[0]->SuccsID.size(); oind++)
{
if (PolicyMDP->StateArray[j]->Actions[0]->SuccsID[oind] == state->StateID) {
//process the predecessor
double PredPc = Pcvals[j];
double OutProb = PolicyMDP->StateArray[j]->Actions[0]->SuccsProb[oind];
//accumulate into Pc
Pc = Pc + OutProb * PredPc;
nMerge++;
//check for cycles
if (bFirstIter && !(*bCycles)) {
if (PathExists(PolicyMDP, state, PolicyMDP->StateArray[j])) *bCycles = true;
}
}
}
}
if (bFirstIter && state->StateID != GoalStateID && nMerge > 0) *nMerges += (nMerge - 1);
//assign Pc
if (state->StateID != StartStateID) Pcvals[i] = Pc;
if (state->StateID == GoalStateID) *Pcgoal = Pcvals[i];
} //over states
bFirstIter = false;
} //until delta small
*PolValue = vals[startind];
SBPL_PRINTF("done\n");
}
void get_bresenham_parameters(int p1x, int p1y, int p2x, int p2y, bresenham_param_t *params)
{
params->UsingYIndex = 0;
if (fabs((double)(p2y - p1y) / (double)(p2x - p1x)) > 1) (params->UsingYIndex)++;
if (params->UsingYIndex) {
params->Y1 = p1x;
params->X1 = p1y;
params->Y2 = p2x;
params->X2 = p2y;
}
else {
params->X1 = p1x;
params->Y1 = p1y;
params->X2 = p2x;
params->Y2 = p2y;
}
if ((p2x - p1x) * (p2y - p1y) < 0) {
params->Flipped = 1;
params->Y1 = -params->Y1;
params->Y2 = -params->Y2;
}
else
params->Flipped = 0;
if (params->X2 > params->X1)
params->Increment = 1;
else
params->Increment = -1;
params->DeltaX = params->X2 - params->X1;
params->DeltaY = params->Y2 - params->Y1;
params->IncrE = 2 * params->DeltaY * params->Increment;
params->IncrNE = 2 * (params->DeltaY - params->DeltaX) * params->Increment;
params->DTerm = (2 * params->DeltaY - params->DeltaX) * params->Increment;
params->XIndex = params->X1;
params->YIndex = params->Y1;
}
void get_current_point(bresenham_param_t *params, int *x, int *y)
{
if (params->UsingYIndex) {
*y = params->XIndex;
*x = params->YIndex;
if (params->Flipped) *x = -*x;
}
else {
*x = params->XIndex;
*y = params->YIndex;
if (params->Flipped) *y = -*y;
}
}
int get_next_point(bresenham_param_t *params)
{
if (params->XIndex == params->X2) {
return 0;
}
params->XIndex += params->Increment;
if (params->DTerm < 0 || (params->Increment < 0 && params->DTerm <= 0))
params->DTerm += params->IncrE;
else {
params->DTerm += params->IncrNE;
params->YIndex += params->Increment;
}
return 1;
}
//converts discretized version of angle into continuous (radians)
//maps 0->0, 1->delta, 2->2*delta, ...
double DiscTheta2Cont(int nTheta, int NUMOFANGLEVALS)
{
double thetaBinSize = 2.0 * PI_CONST / NUMOFANGLEVALS;
return nTheta * thetaBinSize;
}
//converts continuous (radians) version of angle into discrete
//maps 0->0, [delta/2, 3/2*delta)->1, [3/2*delta, 5/2*delta)->2,...
int ContTheta2Disc(double fTheta, int NUMOFANGLEVALS)
{
double thetaBinSize = 2.0 * PI_CONST / NUMOFANGLEVALS;
return (int)(normalizeAngle(fTheta + thetaBinSize / 2.0) / (2.0 * PI_CONST) * (NUMOFANGLEVALS));
}
//input angle should be in radians
//counterclockwise is positive
//output is an angle in the range of from 0 to 2*PI
double normalizeAngle(double angle)
{
double retangle = angle;
//get to the range from -2PI, 2PI
if (fabs(retangle) > 2 * PI_CONST) retangle = retangle - ((int)(retangle / (2 * PI_CONST))) * 2 * PI_CONST;
//get to the range 0, 2PI
if (retangle < 0) retangle += 2 * PI_CONST;
if (retangle < 0 || retangle > 2 * PI_CONST) {
SBPL_ERROR("ERROR: after normalization of angle=%f we get angle=%f\n", angle, retangle);
}
return retangle;
}
/*
* point - the point to test
*
* Function derived from http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/
*/
bool IsInsideFootprint(sbpl_2Dpt_t pt, vector<sbpl_2Dpt_t>* bounding_polygon)
{
int counter = 0;
int i;
double xinters;
sbpl_2Dpt_t p1;
sbpl_2Dpt_t p2;
int N = bounding_polygon->size();
p1 = bounding_polygon->at(0);
for (i = 1; i <= N; i++) {
p2 = bounding_polygon->at(i % N);
if (pt.y > __min(p1.y, p2.y)) {
if (pt.y <= __max(p1.y, p2.y)) {
if (pt.x <= __max(p1.x, p2.x)) {
if (p1.y != p2.y) {
xinters = (pt.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
if (p1.x == p2.x || pt.x <= xinters) counter++;
}
}
}
}
p1 = p2;
}
if (counter % 2 == 0)
return false;
else
return true;
#if DEBUG
//SBPL_PRINTF("Returning from inside footprint: %d\n", c);
#endif
// return c;
}
double computeMinUnsignedAngleDiff(double angle1, double angle2)
{
//get the angles into 0-2*PI range
angle1 = normalizeAngle(angle1);
angle2 = normalizeAngle(angle2);
double anglediff = fabs(angle1 - angle2);
//see if we can take a shorter route
if (anglediff > PI_CONST) {
anglediff = fabs(anglediff - 2 * PI_CONST);
}
return anglediff;
}
//computes 8-connected distances to obstacles and non-free areas in two linear
//passes and returns them in disttoObs_incells
//and disttoNonfree_incells arrays. The distances are in terms of the number of cells but are floats. These distances
//can then be converted into the actual distances using the actual discretization values
//areas outside of the map are considered to be obstacles
void computeDistancestoNonfreeAreas(unsigned char** Grid2D, int width_x, int height_y, unsigned char obsthresh,
float** disttoObs_incells, float** disttoNonfree_incells)
{
int x, y, nbrx, nbry;
float mindisttoObs, mindisttoNonfree;
float maxDist = (float)(__min(width_x, height_y));
float disttoObs, disttoNonfree;
int dir;
const int NUMOF2DQUASIDIRS = 4;
// for quasi-Euclidean distance transform
// going left-to-right, top-to-bottom
int dxdownlefttoright_[NUMOF2DQUASIDIRS];
int dydownlefttoright_[NUMOF2DQUASIDIRS];
int dxdownrighttoleft_[NUMOF2DQUASIDIRS];
int dydownrighttoleft_[NUMOF2DQUASIDIRS];
// going right-to-left, bottom-to-top
int dxuprighttoleft_[NUMOF2DQUASIDIRS];
int dyuprighttoleft_[NUMOF2DQUASIDIRS];
int dxuplefttoright_[NUMOF2DQUASIDIRS];
int dyuplefttoright_[NUMOF2DQUASIDIRS];
// distances to the above nbrs
float distdownlefttoright_[NUMOF2DQUASIDIRS];
float distdownrighttoleft_[NUMOF2DQUASIDIRS];
float distuprighttoleft_[NUMOF2DQUASIDIRS];
float distuplefttoright_[NUMOF2DQUASIDIRS];
// and for distance transform:
// increasing x (outer)
// increasing y (inner)
// [2]
// [1][s]
// [0][3]
dxdownlefttoright_[0] = -1;
dydownlefttoright_[0] = -1;
dxdownlefttoright_[1] = -1;
dydownlefttoright_[1] = 0;
dxdownlefttoright_[2] = -1;
dydownlefttoright_[2] = 1;
dxdownlefttoright_[3] = 0;
dydownlefttoright_[3] = -1;
// increasing x (outer)
// decreasing y (inner)
// [2][3]
// [1][s]
// [0]
dxdownrighttoleft_[0] = -1;
dydownrighttoleft_[0] = -1;
dxdownrighttoleft_[1] = -1;
dydownrighttoleft_[1] = 0;
dxdownrighttoleft_[2] = -1;
dydownrighttoleft_[2] = 1;
dxdownrighttoleft_[3] = 0;
dydownrighttoleft_[3] = 1;
// decreasing x (outer)
// decreasing y (inner)
// [3][2]
// [s][1]
// [0]
dxuprighttoleft_[0] = 1;
dyuprighttoleft_[0] = -1;
dxuprighttoleft_[1] = 1;
dyuprighttoleft_[1] = 0;
dxuprighttoleft_[2] = 1;
dyuprighttoleft_[2] = 1;
dxuprighttoleft_[3] = 0;
dyuprighttoleft_[3] = 1;
// decreasing x (outer)
// increasing y (inner)
// [2]
// [s][1]
// [3][0]
dxuplefttoright_[0] = 1;
dyuplefttoright_[0] = -1;
dxuplefttoright_[1] = 1;
dyuplefttoright_[1] = 0;
dxuplefttoright_[2] = 1;
dyuplefttoright_[2] = 1;
dxuplefttoright_[3] = 0;
dyuplefttoright_[3] = -1;
// insert the corresponding distances
distdownlefttoright_[0] = (float)1.414;
distdownlefttoright_[1] = (float)1.0;
distdownlefttoright_[2] = (float)1.414;
distdownlefttoright_[3] = (float)1.0;
distdownrighttoleft_[0] = (float)1.414;
distdownrighttoleft_[1] = (float)1.0;
distdownrighttoleft_[2] = (float)1.414;
distdownrighttoleft_[3] = (float)1.0;
distuprighttoleft_[0] = (float)1.414;
distuprighttoleft_[1] = (float)1.0;
distuprighttoleft_[2] = (float)1.414;
distuprighttoleft_[3] = (float)1.0;
distuplefttoright_[0] = (float)1.414;
distuplefttoright_[1] = (float)1.0;
distuplefttoright_[2] = (float)1.414;
distuplefttoright_[3] = (float)1.0;
// step through the map from top to bottom,
// alternating left-to-right then right-to-left
// This order maintains the invariant that the min distance for each
// cell to all previously-visited obstacles is accurate
for (x = 0; x < width_x; x++) {
// move from left to right
if (x % 2 == 0) {
for (y = 0; y < height_y; y++) {
mindisttoObs = maxDist; // initialize to max distance
mindisttoNonfree = maxDist;
// if cell is an obstacle, set disttoObs to 0 and continue
if (Grid2D[x][y] >= obsthresh) {
disttoObs_incells[x][y] = 0;
disttoNonfree_incells[x][y] = 0;
continue;
}
if (Grid2D[x][y] > 0) {
mindisttoNonfree = 0;
}
//iterate over predecessors
for (dir = 0; dir < NUMOF2DQUASIDIRS; dir++) {
nbrx = x + dxdownlefttoright_[dir];
nbry = y + dydownlefttoright_[dir];
//make sure it is inside the map and has no obstacle
// compute min cost to an obstacle for each cell, using
// *just* the cells already computed this pass for checking distance
if (nbrx < 0 || nbrx >= width_x || nbry < 0 || nbry >= height_y) {
disttoObs = distdownlefttoright_[dir];
disttoNonfree = disttoObs;
}
else {
disttoObs = distdownlefttoright_[dir] + disttoObs_incells[nbrx][nbry];
disttoNonfree = distdownlefttoright_[dir] + disttoNonfree_incells[nbrx][nbry];
}
if (disttoObs < mindisttoObs) mindisttoObs = disttoObs;
if (disttoNonfree < mindisttoNonfree) mindisttoNonfree = disttoNonfree;
}//over preds
disttoObs_incells[x][y] = mindisttoObs;
disttoNonfree_incells[x][y] = mindisttoNonfree;
}
}
else {
// move from right to left
for (y = height_y - 1; y >= 0; y--) {
mindisttoObs = maxDist; // initialize to max distance
mindisttoNonfree = maxDist;
// if cell is an obstacle, set disttoObs to 0 and continue
if (Grid2D[x][y] >= obsthresh) {
disttoObs_incells[x][y] = 0;
disttoNonfree_incells[x][y] = 0;
continue;
}
if (Grid2D[x][y] > 0) {
mindisttoNonfree = 0;
}
//iterate over predecessors
for (dir = 0; dir < NUMOF2DQUASIDIRS; dir++) {
nbrx = x + dxdownrighttoleft_[dir];
nbry = y + dydownrighttoleft_[dir];
//make sure it is inside the map and has no obstacle
// compute min cost to an obstacle for each cell, using
// *just* the cells already computed this pass for checking distance
if (nbrx < 0 || nbrx >= width_x || nbry < 0 || nbry >= height_y) {
disttoObs = distdownrighttoleft_[dir];
disttoNonfree = disttoObs;
}
else {
disttoObs = distdownrighttoleft_[dir] + disttoObs_incells[nbrx][nbry];
disttoNonfree = distdownrighttoleft_[dir] + disttoNonfree_incells[nbrx][nbry];
}
if (disttoObs < mindisttoObs) mindisttoObs = disttoObs;
if (disttoNonfree < mindisttoNonfree) mindisttoNonfree = disttoNonfree;
}
disttoObs_incells[x][y] = mindisttoObs;
disttoNonfree_incells[x][y] = mindisttoNonfree;
}
//SBPL_PRINTF("x=%d\n", x);
}
}
// step through the map from bottom to top
for (x = width_x - 1; x >= 0; x--) {
// move from right to left
if (x % 2 == 0) {
for (y = height_y - 1; y >= 0; y--) {
// initialize to current distance
mindisttoObs = disttoObs_incells[x][y];
mindisttoNonfree = disttoNonfree_incells[x][y];
//iterate over predecessors
for (dir = 0; dir < NUMOF2DQUASIDIRS; dir++) {
nbrx = x + dxuprighttoleft_[dir];
nbry = y + dyuprighttoleft_[dir];
//make sure it is inside the map and has no obstacle
// compute min cost to an obstacle for each cell, using
// *just* the cells already computed this pass for checking distance
if (nbrx < 0 || nbrx >= width_x || nbry < 0 || nbry >= height_y) {
disttoObs = distuprighttoleft_[dir];
disttoNonfree = disttoObs;
}
else {
disttoObs = distuprighttoleft_[dir] + disttoObs_incells[nbrx][nbry];
disttoNonfree = distuprighttoleft_[dir] + disttoNonfree_incells[nbrx][nbry];
}
if (disttoObs < mindisttoObs) mindisttoObs = disttoObs;
if (disttoNonfree < mindisttoNonfree) mindisttoNonfree = disttoNonfree;
}//over preds
disttoObs_incells[x][y] = mindisttoObs;
disttoNonfree_incells[x][y] = mindisttoNonfree;
}//for y
}
else {
// move from left to right
for (y = 0; y < height_y; y++) {
// initialize to current distance
mindisttoObs = disttoObs_incells[x][y];
mindisttoNonfree = disttoNonfree_incells[x][y];
//iterate over predecessors
for (dir = 0; dir < NUMOF2DQUASIDIRS; dir++) {
nbrx = x + dxuplefttoright_[dir];
nbry = y + dyuplefttoright_[dir];
//make sure it is inside the map and has no obstacle
// compute min cost to an obstacle for each cell, using
// *just* the cells already computed this pass for checking distance
if (nbrx < 0 || nbrx >= width_x || nbry < 0 || nbry >= height_y) {
disttoObs = distuplefttoright_[dir];
disttoNonfree = disttoObs;
}
else {
disttoObs = distuplefttoright_[dir] + disttoObs_incells[nbrx][nbry];
disttoNonfree = distuplefttoright_[dir] + disttoNonfree_incells[nbrx][nbry];
}
if (disttoObs < mindisttoObs) mindisttoObs = disttoObs;
if (disttoNonfree < mindisttoNonfree) mindisttoNonfree = disttoNonfree;
}
disttoObs_incells[x][y] = mindisttoObs;
disttoNonfree_incells[x][y] = mindisttoNonfree;
}//over y
}//direction
}//over x
}
void get_2d_motion_cells(vector<sbpl_2Dpt_t> polygon, vector<sbpl_xy_theta_pt_t> poses, vector<sbpl_2Dcell_t>* cells,
double res)
{
// can't find any motion cells if there are no poses
if (poses.empty()) {
return;
}
//get first footprint set
set<sbpl_2Dcell_t> first_cell_set;
get_2d_footprint_cells(polygon, &first_cell_set, poses[0], res);
//duplicate first footprint set into motion set
set<sbpl_2Dcell_t> cell_set = first_cell_set;
//call get footprint on the rest of the points
for (unsigned int i = 1; i < poses.size(); i++) {
get_2d_footprint_cells(polygon, &cell_set, poses[i], res);
}
//convert the motion set to a vector but don't include the cells in the first footprint set
cells->reserve(cell_set.size() - first_cell_set.size());
for (set<sbpl_2Dcell_t>::iterator it = cell_set.begin(); it != cell_set.end(); it++) {
if (first_cell_set.find(*it) == first_cell_set.end()) {
cells->push_back(*it);
}
}
}
//This function is inefficient and should be avoided if possible (you should
//use overloaded functions that uses a set for the cells)!
void get_2d_footprint_cells(vector<sbpl_2Dpt_t> polygon, vector<sbpl_2Dcell_t>* cells, sbpl_xy_theta_pt_t pose,
double res)
{
set<sbpl_2Dcell_t> cell_set;
for (unsigned int i = 0; i < cells->size(); i++)
cell_set.insert(cells->at(i));
get_2d_footprint_cells(polygon, &cell_set, pose, res);
cells->clear();
cells->reserve(cell_set.size());
//for(set<sbpl_2Dcell_t>::iterator it; it==cell_set.begin(); it++)
// cells->push_back(*it);
for (set<sbpl_2Dcell_t>::iterator it = cell_set.begin(); it != cell_set.end(); it++) {
cells->push_back(*it);
}
}
void get_2d_footprint_cells(vector<sbpl_2Dpt_t> polygon, set<sbpl_2Dcell_t>* cells, sbpl_xy_theta_pt_t pose, double res)
{
//special case for point robot
if (polygon.size() <= 1) {
sbpl_2Dcell_t cell;
cell.x = CONTXY2DISC(pose.x, res);
cell.y = CONTXY2DISC(pose.y, res);
cells->insert(cell);
return;
}
//run bressenham line algorithm around the polygon (add them to the cells set)
//while doing that find the min and max (x,y) and the average x and y
double cth = cos(pose.theta);
double sth = sin(pose.theta);
vector<pair<int, int> > disc_polygon;
disc_polygon.reserve(polygon.size() + 1);
int minx = INFINITECOST;
int maxx = -INFINITECOST;
int miny = INFINITECOST;
int maxy = -INFINITECOST;
//find the bounding box of the polygon
for (unsigned int i = 0; i < polygon.size(); i++) {
pair<int, int> p;
// p.first = CONTXY2DISC(cth*polygon[i].x - sth*polygon[i].y + pose.x, res);
double cx = (cth * polygon[i].x - sth * polygon[i].y + pose.x);
double cy = (sth * polygon[i].x + cth * polygon[i].y + pose.y);
p.first = (int)(cx > 0 ? cx / res + 0.5 : cx / res - 0.5); //(int)(cx / res + 0.5 * sign(c);
// p.second = CONTXY2DISC(sth*polygon[i].x + cth*polygon[i].y + pose.y, res);
p.second = (int)(cy > 0 ? cy / res + 0.5 : cy / res - 0.5);//(int)(cy / res + 0.5);
disc_polygon.push_back(p);
if (p.first < minx) minx = p.first;
if (p.first > maxx) maxx = p.first;
if (p.second < miny) miny = p.second;
if (p.second > maxy) maxy = p.second;
}
disc_polygon.push_back(disc_polygon.front());
//make a grid big enough for the footprint
int sizex = (maxx - minx + 1) + 2;
int sizey = (maxy - miny + 1) + 2;
int** grid = new int*[sizex];
for (int i = 0; i < sizex; i++) {
grid[i] = new int[sizey];
for (int j = 0; j < sizey; j++)
grid[i][j] = 0;
}
//plot line points on the grid
for (unsigned int i = 1; i < disc_polygon.size(); i++) {
int x0 = disc_polygon[i - 1].first - minx + 1;
int y0 = disc_polygon[i - 1].second - miny + 1;
int x1 = disc_polygon[i].first - minx + 1;
int y1 = disc_polygon[i].second - miny + 1;
//bressenham (add the line cells to the set and to a vector)
bool steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
int temp = x0;
x0 = y0;
y0 = temp;
temp = x1;
x1 = y1;
y1 = temp;
}
if (x0 > x1) {
int temp = x0;
x0 = x1;
x1 = temp;
temp = y0;
y0 = y1;
y1 = temp;
}
int deltax = x1 - x0;
int deltay = abs(y1 - y0);
int error = deltax / 2;
int ystep = (y0 < y1 ? 1 : -1);
int y = y0;
for (int x = x0; x <= x1; x++) {
if (steep) {
grid[y][x] = 1;
cells->insert(sbpl_2Dcell_t(y - 1 + minx, x - 1 + miny));
}
else {
grid[x][y] = 1;
cells->insert(sbpl_2Dcell_t(x - 1 + minx, y - 1 + miny));
}
int last_error = error;
error -= deltay;
if (error < 0 && x != x1) {
//make sure we can't have a diagonal line (the 8-connected bfs will leak through)
int tempy = y;
int tempx = x;
if (last_error < -error)
tempy += ystep;
else
tempx += 1;
if (steep) {
grid[tempy][tempx] = 1;
cells->insert(sbpl_2Dcell_t(tempy - 1 + minx, tempx - 1 + miny));
}
else {
grid[tempx][tempy] = 1;
cells->insert(sbpl_2Dcell_t(tempx - 1 + minx, tempy - 1 + miny));
}
y += ystep;
error += deltax;
}
}
}
//run a 2d bfs from the average (x,y)
sbpl_bfs_2d bfs(sizex, sizey, 1);
bfs.compute_distance_from_point(grid, 0, 0);
for (int i = 0; i < sizex; i++)
delete[] grid[i];
delete[] grid;
//add all cells expanded to the cells set
for (int i = 1; i < sizex - 1; i++) {
for (int j = 1; j < sizey - 1; j++) {
if (bfs.get_distance(i, j) < 0) cells->insert(sbpl_2Dcell_t(i - 1 + minx, j - 1 + miny));
}
}
}
void writePlannerStats(vector<PlannerStats> s, FILE* fout)
{
fprintf(fout, "%%eps time expands cost\n");
for (unsigned int i = 0; i < s.size(); i++) {
fprintf(fout, "%f %f %d %d\n", s[i].eps, s[i].time, s[i].expands, s[i].cost);
}
}

View File

@@ -0,0 +1,359 @@
#!/usr/bin/env python
from sys import argv
from subprocess import call
from os import getcwd, chdir, pardir, devnull
from os.path import join, exists, abspath
# This script should only be run from sbpl/test/
sbpl_root = abspath(pardir)
def generate_makefile(dir=''):
"""
Generates a Makefile for SBPL if one doesn't exist
Looks in a directory relative to the current directory for a Makefile. A new one is generated
using CMake if one isn't already there. CMakeLists.txt must exist in that directory for this to
work.
@return Whether or not a Makefile was generated
"""
# try to generate Makefile if one doesn't exist
cwd = join(getcwd(), dir)
print 'Looking for Makefile in', cwd
if not exists(join(cwd, 'Makefile')):
if not exists(join(cwd, 'CMakeLists.txt')):
return False
else:
print 'No Makefile found for SBPL, running cmake'
call(['cmake', '.'])
return exists(join(cwd, 'Makefile'))
#end generate_makefile
def run_sbpl_test(env_type, planner_type, test_env, mprim, is_forward_search, navigating=False):
"""
@brief run the sbpl test executable
"""
sbpl_exe = join(sbpl_root, 'bin/test_sbpl')
devnull_fd = open(devnull) # for surpressing output
test_env_path = join(sbpl_root, test_env)
mprim_path = join(sbpl_root, mprim)
print
print 'Running', planner_type, 'planner on', env_type, 'environment'
print 'Navigating =', navigating
print 'Test environment =', test_env
print 'Motion primitives =', mprim
forward_search_arg = ''
if is_forward_search:
forward_search_arg = 'forward'
else:
forward_search_arg = 'backward'
args = [sbpl_exe, '--env=' + env_type, '--planner=' + planner_type, '--search-dir=' + forward_search_arg, test_env_path, mprim_path]
if mprim == '': args.pop()
if navigating: args.insert(1, '-s')
for arg in args: print arg,
print
import time
start_time = time.time()
sbpl_res = call(args, stdout=devnull_fd, stderr=devnull_fd)
end_time = time.time()
print 'Planning took', end_time - start_time, 'seconds.'
green_color = '\033[92;1m'
red_color = '\033[91;1m'
end_color = '\033[0m'
if sbpl_res == 0:
print green_color + 'Planning succeeded.' + end_color
else:
print red_color + 'Planner failed with exit code' + end_color, sbpl_res
print
devnull_fd.close()
return sbpl_res
#end run_sbpl_test
if __name__ == '__main__':
print "SBPL is located at", sbpl_root
chdir(sbpl_root)
makefile_exists = generate_makefile()
make_result = 0
# build SBPL
if makefile_exists:
if 'rebuild' in argv: call(['make', 'clean'])
make_result = call(['make'])
else:
print 'No Makefile or CMakeLists.txt found. Attempting to run tests without building'
if make_result != 0:
print 'Errors building SBPL. Checking for older version of SBPL...'
sbpl_exists = exists(join(sbpl_root, 'bin/test_sbpl')) and \
exists(join(sbpl_root, 'lib/libsbpl.so'))
if not sbpl_exists:
print 'Could not build SBPL and SBPL is not already pre-built. Aborting tests'
exit()
else:
print 'SBPL library and test executable built. Proceeding with tests.'
num_2d_test_successes = 0
### PLANNING FOR 2D ENVIRONMENTS ###
# all planners on 2d environment (12 tests) env1
if run_sbpl_test('2d', 'arastar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
if run_sbpl_test('2d', 'adstar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
if run_sbpl_test('2d', 'anastar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
if run_sbpl_test('2d', 'rstar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
# all planners navigating on 2d env1
if run_sbpl_test('2d', 'arastar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', True, True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
if run_sbpl_test('2d', 'adstar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', True, True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
if run_sbpl_test('2d', 'anastar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', True, True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
if run_sbpl_test('2d', 'rstar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', True, True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
# all planners on 2d env2
if run_sbpl_test('2d', 'arastar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
if run_sbpl_test('2d', 'adstar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
if run_sbpl_test('2d', 'anastar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
if run_sbpl_test('2d', 'rstar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_2d_test_successes = num_2d_test_successes + 1
# all planners navigating on 2d env2 (no thanks, I want my tests to finish)
#run_sbpl_test('2d', 'arastar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', True)
#run_sbpl_test('2d', 'adstar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', True)
#run_sbpl_test('2d', 'anastar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', True)
#run_sbpl_test('2d', 'rstar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', True)
### PLANNING FOR (X,Y,THETA) ENVIRONMENTS (9 tests) ###
num_xytheta_test_successes = 0
# all planners on xytheta env1
if run_sbpl_test('xytheta', 'arastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_xytheta_test_successes = num_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'adstar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_xytheta_test_successes = num_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'anastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_xytheta_test_successes = num_xytheta_test_successes + 1
# all planners navigating on xytheta env1
if run_sbpl_test('xytheta', 'arastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', True, True) == 0:
num_xytheta_test_successes = num_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'adstar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', True, True) == 0:
num_xytheta_test_successes = num_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'anastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', True, True) == 0:
num_xytheta_test_successes = num_xytheta_test_successes + 1
# all planners on xytheta env2
if run_sbpl_test('xytheta', 'arastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', True) == 0:
num_xytheta_test_successes = num_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'adstar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', True) == 0:
num_xytheta_test_successes = num_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'anastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', True) == 0:
num_xytheta_test_successes = num_xytheta_test_successes + 1
# all planners navigating on xytheta env2 (no thanks, i want my tests to finish)
#run_sbpl_test('xytheta', 'arastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', True)
#run_sbpl_test('xytheta', 'adstar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', True)
#run_sbpl_test('xytheta', 'anstar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', True)
### PLANNING FOR (X,Y,THETA,LEV) ENVIRONMENTS (6 tests) ###
num_xythetamlev_test_successes = 0
# all planners on xythetamlev env1
if run_sbpl_test('xythetamlev', 'arastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_xythetamlev_test_successes = num_xythetamlev_test_successes + 1
if run_sbpl_test('xythetamlev', 'adstar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_xythetamlev_test_successes = num_xythetamlev_test_successes + 1
if run_sbpl_test('xythetamlev', 'anastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', True) == 0:
num_xythetamlev_test_successes = num_xythetamlev_test_successes + 1
# all planners on xythetamlev env2
if run_sbpl_test('xythetamlev', 'arastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', True) == 0:
num_xythetamlev_test_successes = num_xythetamlev_test_successes + 1
if run_sbpl_test('xythetamlev', 'adstar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', True) == 0:
num_xythetamlev_test_successes = num_xythetamlev_test_successes + 1
if run_sbpl_test('xythetamlev', 'anastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', True) == 0:
num_xythetamlev_test_successes = num_xythetamlev_test_successes + 1
### PLANNING FOR ROBARM ENVIRONMENTS (12 tests) ###
num_robarm_test_successes = 0
# all planners on robarm env1
if run_sbpl_test('robarm', 'arastar', 'env_examples/robarm/env1_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
if run_sbpl_test('robarm', 'adstar', 'env_examples/robarm/env1_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
if run_sbpl_test('robarm', 'anastar', 'env_examples/robarm/env1_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
if run_sbpl_test('robarm', 'rstar', 'env_examples/robarm/env1_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
# all planners on robarm env2
if run_sbpl_test('robarm', 'arastar', 'env_examples/robarm/env2_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
if run_sbpl_test('robarm', 'adstar', 'env_examples/robarm/env2_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
if run_sbpl_test('robarm', 'anastar', 'env_examples/robarm/env2_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
if run_sbpl_test('robarm', 'rstar', 'env_examples/robarm/env2_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
# all planners on robarm env3
if run_sbpl_test('robarm', 'arastar', 'env_examples/robarm/env3_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
if run_sbpl_test('robarm', 'adstar', 'env_examples/robarm/env3_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
if run_sbpl_test('robarm', 'anastar', 'env_examples/robarm/env3_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
if run_sbpl_test('robarm', 'rstar', 'env_examples/robarm/env3_6d.cfg', '', True) == 0:
num_robarm_test_successes = num_robarm_test_successes + 1
###### RUN ALL TESTS WITH BACKWARD SEARCH NOW ######
### PLANNING FOR 2D ENVIRONMENTS ###
num_b_2d_test_successes = 0
# all planners on 2d environment (12 tests) env1
if run_sbpl_test('2d', 'arastar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
if run_sbpl_test('2d', 'adstar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
if run_sbpl_test('2d', 'anastar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
if run_sbpl_test('2d', 'rstar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
# all planners navigating on 2d env1
if run_sbpl_test('2d', 'arastar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', False, True) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
if run_sbpl_test('2d', 'adstar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', False, True) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
if run_sbpl_test('2d', 'anastar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', False, True) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
if run_sbpl_test('2d', 'rstar', 'env_examples/nav2d/env1.cfg', 'matlab/mprim/pr2.mprim', False, True) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
# all planners on 2d env2
if run_sbpl_test('2d', 'arastar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
if run_sbpl_test('2d', 'adstar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
if run_sbpl_test('2d', 'anastar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
if run_sbpl_test('2d', 'rstar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_2d_test_successes = num_b_2d_test_successes + 1
# all planners navigating on 2d env2 (no thanks, I want my tests to finish)
#run_sbpl_test('2d', 'arastar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', False)
#run_sbpl_test('2d', 'adstar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', False)
#run_sbpl_test('2d', 'anastar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', False)
#run_sbpl_test('2d', 'rstar', 'env_examples/nav2d/env2.cfg', 'matlab/mprim/pr2.mprim', False)
### PLANNING FOR (X,Y,THETA) ENVIRONMENTS (9 tests) ###
num_b_xytheta_test_successes = 0
# all planners on xytheta env1
if run_sbpl_test('xytheta', 'arastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_xytheta_test_successes = num_b_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'adstar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_xytheta_test_successes = num_b_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'anastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_xytheta_test_successes = num_b_xytheta_test_successes + 1
# all planners navigating on xytheta env1
if run_sbpl_test('xytheta', 'arastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', False, False) == 0:
num_b_xytheta_test_successes = num_b_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'adstar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', False, False) == 0:
num_b_xytheta_test_successes = num_b_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'anastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', False, False) == 0:
num_b_xytheta_test_successes = num_b_xytheta_test_successes + 1
# all planners on xytheta env2
if run_sbpl_test('xytheta', 'arastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', False) == 0:
num_b_xytheta_test_successes = num_b_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'adstar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', False) == 0:
num_b_xytheta_test_successes = num_b_xytheta_test_successes + 1
if run_sbpl_test('xytheta', 'anastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', False) == 0:
num_b_xytheta_test_successes = num_b_xytheta_test_successes + 1
# all planners navigating on xytheta env2 (no thanks, i want my tests to finish)
#run_sbpl_test('xytheta', 'arastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', False)
#run_sbpl_test('xytheta', 'adstar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', False)
#run_sbpl_test('xytheta', 'anstar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', False)
### PLANNING FOR (X,Y,THETA,LEV) ENVIRONMENTS (6 tests) ###
num_b_xythetamlev_test_successes = 0
# all planners on xythetamlev env1
if run_sbpl_test('xythetamlev', 'arastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_xythetamlev_test_successes = num_b_xythetamlev_test_successes + 1
if run_sbpl_test('xythetamlev', 'adstar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_xythetamlev_test_successes = num_b_xythetamlev_test_successes + 1
if run_sbpl_test('xythetamlev', 'anastar', 'env_examples/nav3d/env1.cfg', 'matlab/mprim/pr2.mprim', False) == 0:
num_b_xythetamlev_test_successes = num_b_xythetamlev_test_successes + 1
# all planners on xythetamlev env2
if run_sbpl_test('xythetamlev', 'arastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', False) == 0:
num_b_xythetamlev_test_successes = num_b_xythetamlev_test_successes + 1
if run_sbpl_test('xythetamlev', 'adstar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', False) == 0:
num_b_xythetamlev_test_successes = num_b_xythetamlev_test_successes + 1
if run_sbpl_test('xythetamlev', 'anastar', 'env_examples/nav3d/env2.cfg', 'matlab/mprim/pr2_10cm.mprim', False) == 0:
num_b_xythetamlev_test_successes = num_b_xythetamlev_test_successes + 1
print '\033[96;1m', 'Forward search results', '\033[0m'
print '\033[96;1m', '----------------------', '\033[0m'
print '\033[96;1m', num_2d_test_successes, 'out of', 12, '2d tests succeeded', '\033[0m'
print '\033[96;1m', num_xytheta_test_successes, 'out of', 9, 'xytheta tests succeeded.', '\033[0m'
print '\033[96;1m', num_xythetamlev_test_successes, 'out of', 6, 'xythetamlev tests succeeded.', '\033[0m'
print '\033[96;1m', num_robarm_test_successes, 'out of', 12, 'robarm tests succeeded.', '\033[0m'
num_tests = 39
print '\033[96;1m', num_2d_test_successes + num_xytheta_test_successes + num_xythetamlev_test_successes + \
num_robarm_test_successes, 'out of', num_tests, 'tests succeeded.', '\033[0m'
print
print '\033[96;1m', 'Backward search results', '\033[0m'
print '\033[96;1m', '-----------------------', '\033[0m'
print '\033[96;1m', num_b_2d_test_successes, 'out of', 12, '2d tests succeeded', '\033[0m'
print '\033[96;1m', num_b_xytheta_test_successes, 'out of', 9, 'xytheta tests succeeded.', '\033[0m'
print '\033[96;1m', num_b_xythetamlev_test_successes, 'out of', 6, 'xythetamlev tests succeeded.', '\033[0m'
num_b_tests = 27
print '\033[96;1m', num_b_2d_test_successes + num_b_xytheta_test_successes + num_b_xythetamlev_test_successes, \
'out of', num_b_tests, 'tests succeeded.', '\033[0m'
#end main
# NOTES
# xytheta and xythetamlev environments do not support R* planning
# envrobarm does not support backward search