Skip to content

Commit

Permalink
Fix SoPlex interface and compilation with CPLEX on Windows.
Browse files Browse the repository at this point in the history
  • Loading branch information
jendrikseipp authored Oct 5, 2023
1 parent 690c1d2 commit 414535d
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 87 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,15 @@ jobs:
echo "https://www.ibm.com/docs/en/icos/22.1.1?topic=2211-silent-installation-cplex-optimization-studio"
curl.exe --output cplex.exe $ENV:CPLEX_URL
# This directory only already exists for repos called "downward".
mkdir D:\a\downward
echo "Install CPLEX"
Start-Process -FilePath .\cplex.exe -ArgumentList "-f", "D:\a\downward\downward\.github\workflows\misc\cplex2211_windows_installer.properties" -PassThru | Wait-Process
Start-Process -FilePath .\cplex.exe -ArgumentList "-f", "$ENV:GITHUB_WORKSPACE\.github\workflows\misc\cplex2211_windows_installer.properties" -PassThru | Wait-Process
del .\cplex.exe
echo "Copy the relevant directory to a location which is not magically protected against cmake"
Xcopy /E /I ..\cplex_temp\cplex ..\cplex
Xcopy /E /I D:\a\downward\cplex_temp\cplex $ENV:cplex_DIR
- name: Compile planner
Expand Down
12 changes: 4 additions & 8 deletions misc/tests/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,10 @@ def configs_optimal_extended():
"""astar(ucp([projections(systematic(2))]))"""],
"oucp": [
"--search",
"""astar(ucp(
[projections(systematic(2))], opportunistic=true, max_orders=1))"""],
"""astar(ucp([projections(systematic(2))], opportunistic=true, max_orders=1))"""],
"gzocp": [
"--search",
"""astar(gzocp(
[projections(systematic(2))], max_orders=1))"""],
"""astar(gzocp([projections(systematic(2))], max_orders=1))"""],
"lm_ucp":
_get_landmark_config(cost_partitioning="uniform"),
"lm_can": _get_landmark_config(cost_partitioning="canonical"),
Expand Down Expand Up @@ -240,12 +238,10 @@ def configs_optimal_lp(lp_solver="cplex"):
f"""astar(ocp([projections(systematic(2))], lpsolver={lp_solver}))"""],
"pho": [
"--search",
f"""astar(operatorcounting([pho_abstraction_constraints(
[projections(systematic(2))], saturated=false)], lpsolver={lp_solver}))"""],
f"""astar(operatorcounting([pho_abstraction_constraints([projections(systematic(2))], saturated=false)], lpsolver={lp_solver}))"""],
"spho": [
"--search",
f"""astar(operatorcounting([pho_abstraction_constraints(
[projections(systematic(2))], saturated=true)], lpsolver={lp_solver}))"""],
f"""astar(operatorcounting([pho_abstraction_constraints([projections(systematic(2))], saturated=true)], lpsolver={lp_solver}))"""],
"spho_offline": [
"--search",
"""astar(pho([projections(systematic(2))], saturated=true, max_orders=1))"""],
Expand Down
1 change: 0 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,5 @@ add_custom_command(TARGET translate POST_BUILD
COMMENT "Copying translator module into output directory")

# Add search component as a subproject.
set(FAST_DOWNWARD_MAIN_CMAKELISTS_READ TRUE)
add_subdirectory(preprocess_h2)
add_subdirectory(search)
97 changes: 76 additions & 21 deletions src/preprocess_h2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
if(NOT FAST_DOWNWARD_MAIN_CMAKELISTS_READ)
message(
FATAL_ERROR
"Run cmake on the CMakeLists.txt in the 'src' directory. "
"Please delete CMakeCache.txt from the current directory "
"and restart cmake.")
endif()

cmake_minimum_required(VERSION 3.16)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/ext)

# Path containing custom CMake modules
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../search/cmake)
include(common_cxx_flags)
include(macros)
include(options)

report_bitwidth()
#set_up_build_types("Debug;Release")

project(preprocess-h2 LANGUAGES CXX)

set(PREPROCESS_SOURCES
Expand All @@ -36,3 +15,79 @@ set(PREPROCESS_SOURCES
)

add_executable(preprocess-h2 ${PREPROCESS_SOURCES})

macro(check_and_set_compiler_flag FLAG)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag( "${FLAG}" FLAG_FOUND )
if(NOT FLAG_FOUND)
message(FATAL_ERROR "${CMAKE_CXX_COMPILER} does not support ${FLAG}")
endif()
message("Flag '${FLAG}' set for '${CMAKE_CXX_COMPILER}'")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}")
endmacro()

macro(fast_downward_set_compiler_flags)
set(non_windows_compilers "GNU" "Clang" "AppleClang")
if(${CMAKE_CXX_COMPILER_ID} IN_LIST non_windows_compilers)
check_and_set_compiler_flag( "-std=c++20" )

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wnon-virtual-dtor")

if (CMAKE_COMPILER_IS_GNUCXX
AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12
AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13)
## We ignore the warning "restrict" because of a bug in GCC 12:
## https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105651
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-restrict")
endif()

## Configuration-specific flags
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -fomit-frame-pointer")
set(CMAKE_CXX_FLAGS_DEBUG "-O3")
if(USE_GLIBCXX_DEBUG)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_GLIBCXX_DEBUG")
endif()
set(CMAKE_CXX_FLAGS_PROFILE "-O3 -pg")
elseif(MSVC)
check_and_set_compiler_flag( "/std:c++20" )

# Enable exceptions.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")

# Use warning level 4 (/W4).
# /Wall currently detects too many warnings outside of our code to be useful.
string(REPLACE "/W3" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

# Disable warnings that currently trigger in the code until we fix them.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800") # forcing value to bool
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4512") # assignment operator could not be generated
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4706") # assignment within conditional expression (in tree.hh)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4100") # unreferenced formal parameter (in OSI)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4127") # conditional expression is constant (in tree.hh and in our code)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244") # conversion with possible loss of data
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4309") # truncation of constant value (in OSI, see issue857)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4702") # unreachable code
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4239") # nonstandard extension used
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") # function call with parameters that may be unsafe
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4456") # declaration hides previous local declaration
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4458") # declaration hides class member
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267") # conversion from size_t to int with possible loss of data

# The following are disabled because of what seems to be compiler bugs.
# "unreferenced local function has been removed";
# see http://stackoverflow.com/questions/3051992/compiler-warning-at-c-template-base-class
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4505")
else()
message(FATAL_ERROR "Unsupported compiler: ${CMAKE_CXX_COMPILER}")
endif()
endmacro()

macro(fast_downward_set_linker_flags)
if(UNIX)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g")
endif()
endmacro()

fast_downward_set_compiler_flags()
fast_downward_set_linker_flags()
1 change: 1 addition & 0 deletions src/search/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,7 @@ create_fast_downward_library(
operator_counting/delete_relaxation_constraints
operator_counting/lm_cut_constraints
operator_counting/operator_counting_heuristic
operator_counting/pho_abstraction_constraints
operator_counting/pho_constraints
operator_counting/state_equation_constraints
DEPENDS lp_solver landmark_cut_heuristic pdbs task_properties
Expand Down
2 changes: 0 additions & 2 deletions src/search/cartesian_abstractions/abstract_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ class State;
class TaskProxy;

namespace cartesian_abstractions {
class Node;

/*
Store the Cartesian set and the ID of the node in the refinement hierarchy
for an abstract state.
Expand Down
4 changes: 2 additions & 2 deletions src/search/cartesian_abstractions/flaw.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using namespace std;

namespace cartesian_abstractions {
const FlawedState FlawedState::no_state = FlawedState(-1, -1, {});
const FlawedState FlawedState::no_state = FlawedState(-1, UNDEFINED_COST, {});

bool FlawedStates::is_consistent() const {
return flawed_states_queue.size() == static_cast<int>(flawed_states.size());
Expand Down Expand Up @@ -53,7 +53,7 @@ FlawedState FlawedStates::pop_random_flawed_state_and_clear(utils::RandomNumberG
vector<StateID> conc_states = move(random_bucket->second);
clear();
assert(is_consistent());
return FlawedState(abstract_state_id, -1, move(conc_states));
return FlawedState(abstract_state_id, UNDEFINED_COST, move(conc_states));
}

int FlawedStates::num_abstract_states() const {
Expand Down
3 changes: 2 additions & 1 deletion src/search/cartesian_abstractions/flaw.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
#include "shortest_paths.h"
#include "types.h"

#include "../state_id.h"

#include "../utils/hash.h"

#include <utility>

class State;
class StateID;

namespace utils {
class RandomNumberGenerator;
Expand Down
83 changes: 40 additions & 43 deletions src/search/cartesian_abstractions/refinement_hierarchy.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,6 @@ class AbstractTask;
class State;

namespace cartesian_abstractions {
class Node;

/*
This class stores the refinement hierarchy of a Cartesian
abstraction. The hierarchy forms a DAG with inner nodes for each
split and leaf nodes for the abstract states.
It is used for efficient lookup of abstract states during search.
Inner nodes correspond to abstract states that have been split (or
helper nodes, see below). Leaf nodes correspond to the current
(unsplit) states in an abstraction. The use of helper nodes makes
this structure a directed acyclic graph (instead of a tree).
*/
class RefinementHierarchy {
std::shared_ptr<AbstractTask> task;
std::vector<Node> nodes;

NodeID add_node(int state_id);
NodeID get_node_id(const State &state) const;

public:
explicit RefinementHierarchy(const std::shared_ptr<AbstractTask> &task);

/*
Update the split tree for the new split. Additionally to the left
and right child nodes add |values|-1 helper nodes that all have
the right child as their right child and the next helper node as
their left child.
*/
std::pair<NodeID, NodeID> split(
NodeID node_id, int var, const std::vector<int> &values,
int left_state_id, int right_state_id);

int get_abstract_state_id(const State &state) const;
friend int Abstraction::get_abstract_state_id(const State &state) const;

int get_num_nodes() const {
return nodes.size();
}
};


class Node {
/*
While right_child is always the node of a (possibly split)
Expand Down Expand Up @@ -101,6 +58,46 @@ class Node {

friend std::ostream &operator<<(std::ostream &os, const Node &node);
};

/*
This class stores the refinement hierarchy of a Cartesian
abstraction. The hierarchy forms a DAG with inner nodes for each
split and leaf nodes for the abstract states.
It is used for efficient lookup of abstract states during search.
Inner nodes correspond to abstract states that have been split (or
helper nodes, see below). Leaf nodes correspond to the current
(unsplit) states in an abstraction. The use of helper nodes makes
this structure a directed acyclic graph (instead of a tree).
*/
class RefinementHierarchy {
std::shared_ptr<AbstractTask> task;
std::vector<Node> nodes;

NodeID add_node(int state_id);
NodeID get_node_id(const State &state) const;

public:
explicit RefinementHierarchy(const std::shared_ptr<AbstractTask> &task);

/*
Update the split tree for the new split. Additionally to the left
and right child nodes add |values|-1 helper nodes that all have
the right child as their right child and the next helper node as
their left child.
*/
std::pair<NodeID, NodeID> split(
NodeID node_id, int var, const std::vector<int> &values,
int left_state_id, int right_state_id);

int get_abstract_state_id(const State &state) const;
friend int Abstraction::get_abstract_state_id(const State &state) const;

int get_num_nodes() const {
return nodes.size();
}
};
}

#endif
4 changes: 2 additions & 2 deletions src/search/cartesian_abstractions/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ using Loops = std::vector<int>;
using Solution = std::deque<Transition>;
using Transitions = std::vector<Transition>;

const int UNDEFINED = -1;

// Positive infinity. The name "INFINITY" is taken by an ISO C99 macro.
const int INF = std::numeric_limits<int>::max();
const int UNDEFINED = -1;
const Cost INF_COSTS = std::numeric_limits<Cost>::max();
const Cost UNDEFINED_COST = std::numeric_limits<Cost>::max() - 1;
}

#endif
2 changes: 1 addition & 1 deletion src/search/lp/lp_solver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ void LPSolver::set_variable_lower_bound(int index, double bound) {
}

void LPSolver::set_variable_upper_bound(int index, double bound) {
pimpl->set_constraint_upper_bound(index, bound);
pimpl->set_variable_upper_bound(index, bound);
}

void LPSolver::set_mip_gap(double gap) {
Expand Down
8 changes: 4 additions & 4 deletions src/search/lp/soplex_solver_interface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ SoPlexSolverInterface::SoPlexSolverInterface() : SolverInterface() {
void SoPlexSolverInterface::load_problem(const LinearProgram &lp) {
for (const LPVariable &var : lp.get_variables()) {
if (var.is_integer) {
cout << "SoPlex does not support integer variables" << endl;
cerr << "SoPlex does not support integer variables" << endl;
utils::exit_with(utils::ExitCode::SEARCH_UNSUPPORTED);
}
}
Expand Down Expand Up @@ -105,18 +105,18 @@ void SoPlexSolverInterface::set_constraint_upper_bound(int index, double bound)
}

void SoPlexSolverInterface::set_variable_lower_bound(int index, double bound) {
soplex.changeUpperReal(index, bound);
soplex.changeLowerReal(index, bound);
}

void SoPlexSolverInterface::set_variable_upper_bound(int index, double bound) {
soplex.changeLowerReal(index, bound);
soplex.changeUpperReal(index, bound);
}

void SoPlexSolverInterface::set_mip_gap(double /*gap*/) {
/*
There is nothing to do here: Soplex doesn't accept MIPs, so setting a MIP
gap tolerance has no effect. We do not treat it as an error, so solvers
can be set up without cheking what problems they will eventually solve.
can be set up without checking what problems they will eventually solve.
Loading a problem with integer variables will lead to an error either way.
*/
}
Expand Down

0 comments on commit 414535d

Please sign in to comment.