Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ PointerAlignment: Left
UseTab: ForIndentation
IndentWidth: 4
TabWidth: 4
# ColumnLimit: 120
Cpp11BracedListStyle: true
AlwaysBreakTemplateDeclarations: Yes
AlwaysBreakAfterReturnType: All
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
9 changes: 6 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
cmake_minimum_required(VERSION 3.13)

project(WarthogJPS
VERSION 0.2.0
VERSION 0.5.0
LANGUAGES CXX C)

set_property(GLOBAL PROPERTY WARTHOG_warthog-jps ON)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

include(cmake/submodule.cmake)
include(cmake/warthog.cmake)
warthog_module_declare(warthog-core v0.5.0)
warthog_module(warthog-core)

add_library(warthog_libjps)
add_library(warthog::libjps ALIAS warthog_libjps)
Expand All @@ -26,4 +30,3 @@ target_link_libraries(warthog_jps PUBLIC warthog::libjps)
add_subdirectory(src)
add_subdirectory(apps)

warthog_submodule(warthog-core)
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2024 Shortest Path Lab @ Monash University
Copyright (c) 2024-2025 Shortest Path Lab @ Monash University

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
71 changes: 70 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,73 @@

Warthog is an optimised C++ library for pathfinding search.
Warthog-JPS is an extension to Warthog with JPS support.
See [warthog-core](https://github.com/ShortestPathLab/warthog-core) for extended README.
See [warthog-core](https://github.com/ShortestPathLab/warthog-core) for more details on Warthog setup.

If you find this work useful, please cite our paper as follows:

@article{Harabor_Grastien_2014,
title={Improving Jump Point Search},
volume={24},
url={https://ojs.aaai.org/index.php/ICAPS/article/view/13633},
DOI={10.1609/icaps.v24i1.13633},
number={1},
journal={Proceedings of the International Conference on Automated Planning and Scheduling},
author={Harabor, Daniel and Grastien, Alban},
year={2014},
pages={128-135}
}

# Using JPS

## Compile

Program `warthog-jps` uses cmake for the compile process.
Simply run the following code below:

```
cmake -DCMAKE_BUILD_TYPE=Release -B build
cmake --build build
./build/warthog-jps --alg jps --scen example/arena2.map.scen
```

The example map is from the MovingAI benchmarks under Dragon Age Origins.
Use the `build.sh` or `run.sh` for quick compile/usage of this scenario.

For more evaluation data, please refer to existing benchmarks from the community, which offer a range of different challenges across a variety of maps/domains; links found in the resource section.

JPS requires `warthog-core` repo to compile, and by default will fetch the repo.

## JPS Variants

JPS comes with several variants.
All variants use block-based symmetry breaking for finding jump-point locations,
making them at least JPS (B).
The list is as follows:

- `jps` JPS (B) like original with block-based symmetry
- `jpsP` or `jps2` JPS (B+P) with intercardinal pruning
- `jps+` JPS+ (B) is original with offline jump points
- `jpsP+` or `jps2+` JPS+ (B+P) offline with pruning

These jump points are found in namespace `jps::jump`, while `jps::search` uses provided `jps::jump` locators
to produce successors used in warthog-core.

The algorithms provided to `--alg` parameter, along with their `jps::search` and `jps::jump` classes presented
in the table below:

| `--alg` | `jps::search` | `jps::jump` |
|--------------------|--------------------------------|------------------------|
| `jps` | `jps_expansion_policy<>` | `jump_point_online` |
| `jpsP` or `jps2` | `jps_prune_expansion_policy<>` | `jump_point_online` |
| `jps+` | `jps_expansion_policy` | `jump_point_offline<>` |
| `jpsP+` or `jps2+` | `jps_prune_expansion_policy<>` | `jump_point_offline<>` |

## Use in project

If elements of warthog is used in a project, follow guides from `warthog-core` to set up the project structure.

# Resources

- [Moving AI Lab](https://movingai.com/): pathfinding benchmark and tools
- [Posthoc](https://posthoc-app.pathfinding.ai/): visualiser and debugger for pathfinding
- [Pathfinding Benchmarks](https://benchmarks.pathfinding.ai/): git repo for benchmarks
64 changes: 20 additions & 44 deletions apps/jps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@
//

#include <jps/search/jps.h>
#include <jps/search/jps2_expansion_policy.h>
#include <jps/search/jps2plus_expansion_policy.h>
#include <jps/search/jps4c_expansion_policy.h>
#include <jps/search/jps_expansion_policy.h>
#include <jps/search/jpsplus_expansion_policy.h>
#include <warthog/constants.h>
#include <warthog/domain/gridmap.h>
#include <warthog/heuristic/octile_heuristic.h>
Expand All @@ -21,7 +16,10 @@
#include <warthog/util/scenario_manager.h>
#include <warthog/util/timer.h>

#include <jps/search/jps_expansion_policy2.h>
#include <jps/jump/jump_point_offline.h>
#include <jps/jump/jump_point_online.h>
#include <jps/search/jps_expansion_policy.h>
#include <jps/search/jps_prune_expansion_policy.h>

#include "cfg.h"
#include <getopt.h>
Expand Down Expand Up @@ -70,8 +68,7 @@ help(std::ostream& out)
<< "Invoking the program this way solves all instances in [scen "
"file] with algorithm [alg]\n"
<< "Currently recognised values for [alg]:\n"
<< "\tjps, jps+, jps2, jps2+\n"
<< "\tjpsV2, jpsV2-cardinal, jpsV2-prune\n";
<< "\tjps, jpsP or jps2, jps+, jpsP+ or jps2+\n";
// << ""
// << "The following are valid parameters for GENERATING instances:\n"
// << "\t --gen [map file (required)]\n"
Expand All @@ -90,20 +87,12 @@ check_optimality(

if(fabs(delta - epsilon) > epsilon)
{
std::stringstream strpathlen;
strpathlen << std::fixed << std::setprecision(exp->precision());
strpathlen << sol.sum_of_edge_costs_;

std::stringstream stroptlen;
stroptlen << std::fixed << std::setprecision(exp->precision());
stroptlen << exp->distance();

std::cerr << std::setprecision(exp->precision());
std::cerr << std::setprecision(15);
std::cerr << "optimality check failed!" << std::endl;
std::cerr << std::endl;
std::cerr << "optimal path length: " << stroptlen.str()
std::cerr << "optimal path length: " << exp->distance()
<< " computed length: ";
std::cerr << strpathlen.str() << std::endl;
std::cerr << sol.sum_of_edge_costs_ << std::endl;
std::cerr << "precision: " << precision << " epsilon: " << epsilon
<< std::endl;
std::cerr << "delta: " << delta << std::endl;
Expand Down Expand Up @@ -253,39 +242,26 @@ main(int argc, char** argv)
using namespace jps::search;
if(alg == "jps")
{
return run_jps<jps_expansion_policy>(scenmgr, mapfile, alg);
}
else if(alg == "jps+")
{
return run_jps<jpsplus_expansion_policy>(scenmgr, mapfile, alg);
}
else if(alg == "jps2")
{
return run_jps<jps2_expansion_policy>(scenmgr, mapfile, alg);
}
else if(alg == "jps2+")
{
return run_jps<jps2plus_expansion_policy>(scenmgr, mapfile, alg);
using jump_point = jps::jump::jump_point_online;
return run_jps<jps_expansion_policy<jump_point>>(
scenmgr, mapfile, alg);
}
else if(alg == "jpsV2")
else if(alg == "jpsP" || alg == "jps2")
{
using jump_point
= jps::jump::jump_point_online<jps::JpsFeature::DEFAULT>;
return run_jps<jps_expansion_policy2<jump_point>>(
using jump_point = jps::jump::jump_point_online;
return run_jps<jps_prune_expansion_policy<jump_point>>(
scenmgr, mapfile, alg);
}
else if(alg == "jpsV2-cardinal")
else if(alg == "jps+")
{
using jump_point = jps::jump::jump_point_online<
jps::JpsFeature::STORE_CARDINAL_JUMP>;
return run_jps<jps_expansion_policy2<jump_point>>(
using jump_point = jps::jump::jump_point_offline<>;
return run_jps<jps_expansion_policy<jump_point>>(
scenmgr, mapfile, alg);
}
else if(alg == "jpsV2-prune")
else if(alg == "jpsP+" || alg == "jps2+")
{
using jump_point = jps::jump::jump_point_online<
jps::JpsFeature::PRUNE_INTERCARDINAL>;
return run_jps<jps_expansion_policy2<jump_point>>(
using jump_point = jps::jump::jump_point_offline<>;
return run_jps<jps_prune_expansion_policy<jump_point>>(
scenmgr, mapfile, alg);
}
else
Expand Down
20 changes: 10 additions & 10 deletions cmake/headers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ cmake_minimum_required(VERSION 3.13)
# find include/jps -type f -name '*.h' | sort
target_sources(warthog_libjps PUBLIC
include/jps/forward.h
include/jps/jump/four_connected_jps_locator.h
include/jps/jump/offline_jump_point_locator.h
include/jps/jump/offline_jump_point_locator2.h
include/jps/jump/online_jump_point_locator.h
include/jps/jump/online_jump_point_locator2.h

include/jps/search/jps2_expansion_policy.h
include/jps/search/jps.h
include/jps/search/jps2plus_expansion_policy.h
include/jps/search/jps4c_expansion_policy.h
include/jps/domain/rotate_gridmap.h

include/jps/jump/block_online.h
include/jps/jump/jump.h
include/jps/jump/jump_point_offline.h
include/jps/jump/jump_point_online.h

include/jps/search/jps_expansion_policy_base.h
include/jps/search/jps_expansion_policy.h
include/jps/search/jpsplus_expansion_policy.h
include/jps/search/jps.h
include/jps/search/jps_prune_expansion_policy.h
)
35 changes: 0 additions & 35 deletions cmake/submodule.cmake

This file was deleted.

76 changes: 76 additions & 0 deletions cmake/warthog.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
cmake_minimum_required(VERSION 3.13)

# include this file to check submodule include

# set here as only
set(warthog_https_warthog-core "https://github.com/ShortestPathLab/warthog-core.git" CACHE INTERNAL "")
set(warthog_https_warthog-jps "https://github.com/ShortestPathLab/warthog-jps.git" CACHE INTERNAL "")

if(COMMAND warthog_module)
return() # do not redefine
endif()

include(FetchContent)

set(WARTHOG_MODULE_ROOT_ONLY ON CACHE BOOL "add submodule if present only allowed for root project")

function(warthog_top_level)
set(_is_top OFF)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.21)
if(${PROJECT_IS_TOP_LEVEL})
set(_is_top ON)
endif()
else()
if(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
set(_is_top ON)
endif()
endif()
set(_warthog_is_top ${_is_top} PARENT_SCOPE)
endfunction()

# warthog_module module [override_top]
# adds a module to warthog
# has checks to insure module is only added once
# if called from the top level project (or optional variable override_top is true)
# then if extern/${module}/CMakeLists.txt exists, adds that version instead
# intended for use with git module/subtree.
# otherwise, fetchcontent ${module} is made available
# user must add FetchContent_Declare
function(warthog_module module)
get_property(_module_added GLOBAL PROPERTY WARTHOG_${module} SET)
if(${_module_added}) # module already added
return()
endif()
if((${ARGC} GREATER 1) AND (${ARGV1}))
set(is_top_level ON)
else()
warthog_top_level()
set(is_top_level ${_warthog_is_top})
endif()
if(${is_top_level})
if(EXISTS "${PROJECT_SOURCE_DIR}/extern/${module}/CMakeLists.txt")
# module or subtree, include and exit
add_subdirectory("${PROJECT_SOURCE_DIR}/extern/${module}")
set_property(GLOBAL PROPERTY WARTHOG_${module} ON)
return()
endif()
endif()
# failed to add module, fetch if able
warthog_module_declare(${module})
FetchContent_MakeAvailable(${module})
set_property(GLOBAL PROPERTY WARTHOG_${module} ON)
endfunction()

function(warthog_module_declare module)
if(NOT DEFINED warthog_https_${module})
return()
endif()
if((${ARGC} GREATER 1))
set(git_tag ${ARGV1})
else()
set(git_tag "main")
endif()
FetchContent_Declare(${module}
GIT_REPOSITORY ${warthog_https_${module}}
GIT_TAG ${git_tag})
endfunction()
Loading