Skip to content

Commit

Permalink
Merge pull request #105 from IOHprofiler/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
jacobdenobel authored Oct 24, 2021
2 parents a9b6000 + 21491bb commit 4386bc3
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 25 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ endif()

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -std=c++17 -lstdc++fs")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -ffast-math")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -ffast-math")
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
link_libraries(stdc++fs)
add_compile_definitions(FSEXPERIMENTAL)
endif()
endif()

# Define project targets.
file(GLOB_RECURSE HEADERS include/ioh *.hpp)

Expand Down
10 changes: 10 additions & 0 deletions include/ioh/common/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@ namespace ioh::common
return it == known_ids.end() ? id : get_next_id(known_ids);
}

//! Get the next available id
[[nodiscard]] int check_or_get_next_available(const int id, const std::string& name) const {
const auto already_defined = name_map.find(name) != std::end(name_map);
if(already_defined)
for (const auto kv: id_map)
if (kv.second == name)
return kv.first;
return check_or_get_next_available(id);
}

//! Accessor for the list of registered names
[[nodiscard]] std::vector<std::string> names() const { return common::keys(name_map); }

Expand Down
3 changes: 2 additions & 1 deletion include/ioh/logger/eah.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1081,9 +1081,10 @@ namespace ioh
template <class BinaryOperation>
double accumulate(const EAH &logger, double init, BinaryOperation op)
{
#ifndef NDEBUG
const AttainmentSuite &attainment = logger.data();
assert(attainment.size() > 0);

#endif
Histogram histo;
Histogram::Mat mat = histo(logger);
assert(histo.nb_attainments() > 0);
Expand Down
3 changes: 2 additions & 1 deletion include/ioh/problem/problem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ namespace ioh
Constraint<T> constraint = Constraint<T>())
{
auto &factory = ProblemFactoryType<Problem<T>>::instance();
int id = factory.check_or_get_next_available(1);

int id = factory.check_or_get_next_available(1, name);

factory.include(name, id, [=](const int, const int dimension)
{
Expand Down
33 changes: 19 additions & 14 deletions ioh/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
'''Python specific functions for IOH package
TODO: best far precision
TODO: tracking of out-of bounds
TODO: Check quadratic function, min dimension bbob=2
TODO: Rename Integer -> Discrete
'''

Expand Down Expand Up @@ -36,7 +34,7 @@

ProblemType = typing.Union[problem.Real, problem.Integer]

def get_problem(fid: int, iid: int, dim: int, problem_type: str = "Real") -> ProblemType:
def get_problem(fid: typing.Union[int, str], iid: int, dim: int, problem_type: str = "Real") -> ProblemType:
'''Instantiate a problem based on its function ID, dimension, instance and suite
Parameters
Expand All @@ -52,15 +50,22 @@ def get_problem(fid: int, iid: int, dim: int, problem_type: str = "Real") -> Pro
Only used if fid is an int.
'''
if problem_type in ("BBOB", "Real",):
return getattr(problem, problem_type).create(fid, iid, dim)
elif problem_type in ("PBO", "Integer",):
if fid in [21, 23, "IsingTriangular", "NQueens"]:
if not math.sqrt(dim).is_integer():
raise ValueError("For this function, the dimension needs to be a perfect square!")
return getattr(problem, problem_type).create(fid, iid, dim)
if problem_type in ("PBO", "Integer",) and fid in [21, 23, "IsingTriangular", "NQueens"]:
if not math.sqrt(dim).is_integer():
raise ValueError("For this function, the dimension needs to be a perfect square!")

raise ValueError(f"Suite {problem_type} is not yet supported")
bbob_fns = getattr(problem, "BBOB").problems.values() | getattr(problem, "BBOB").problems.keys()
if problem_type in ("BBOB", "Real",) and fid in bbob_fns:
if not dim >= 2:
raise ValueError("For BBOB functions the minimal dimension is 2")

base_problem = getattr(problem, problem_type)
if base_problem:
if fid not in (base_problem.problems.values() | base_problem.problems.keys()):
raise ValueError(f"{fid} is not registered for problem type: {problem_type}")
return base_problem.create(fid, iid, dim)

raise ValueError(f"Problem type {problem_type} is not supported")

class Experiment:
def __init__(self,
Expand Down Expand Up @@ -192,7 +197,7 @@ def __init__(self,
for attr in itertools.chain(self.run_attributes, self.logged_attributes):
if not hasattr(self.algorithm, attr):
raise TypeError(
f"Attribute {attr} is a member of algorithm {self.algorithm}"
f"Attribute {attr} is not a member of algorithm {self.algorithm}"
)


Expand All @@ -217,8 +222,8 @@ def evaluate(self, fid: int, iid: int, dim: int):
if self.logged:
l = logger.Analyzer(**self.logger_params)
l.set_experiment_attributes(self.experiment_attributes)
l.add_run_attributes(self.algorithm, self.run_attributes)
l.watch(self.algorithm, self.logged_attributes)
l.add_run_attributes(algorithm, self.run_attributes)
l.watch(algorithm, self.logged_attributes)

p.attach_logger(l)
self.apply(algorithm, p)
Expand Down
4 changes: 2 additions & 2 deletions ioh/iohcpp/problem.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -206,5 +206,5 @@ class WModelOneMax(AbstractWModel):
class Weierstrass(Real):
def __init__(self, arg0: int, arg1: int) -> None: ...

def wrap_integer_problem(f: function, name: str, n_variables: int = ..., optimization_type: ioh.iohcpp.OptimizationType = ..., constraint: ioh.iohcpp.IntegerConstraint = ...) -> IntegerWrappedProblem: ...
def wrap_real_problem(f: function, name: str, n_variables: int = ..., optimization_type: ioh.iohcpp.OptimizationType = ..., constraint: ioh.iohcpp.RealConstraint = ...) -> RealWrappedProblem: ...
def wrap_integer_problem(f: handle, name: str, n_variables: int = ..., optimization_type: ioh.iohcpp.OptimizationType = ..., constraint: ioh.iohcpp.IntegerConstraint = ...) -> IntegerWrappedProblem: ...
def wrap_real_problem(f: handle, name: str, n_variables: int = ..., optimization_type: ioh.iohcpp.OptimizationType = ..., constraint: ioh.iohcpp.RealConstraint = ...) -> RealWrappedProblem: ...
20 changes: 15 additions & 5 deletions ioh/src/problem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <pybind11/stl.h>
#include "ioh.hpp"


namespace py = pybind11;
using namespace ioh::problem;

Expand Down Expand Up @@ -187,6 +188,8 @@ void define_base_class(py::module &m, const std::string &name)
});
}

static std::vector<py::handle> WRAPPED_FUNCTIONS;

template <typename T>
void define_wrapper_functions(py::module &m, const std::string &class_name, const std::string &function_name)
{
Expand All @@ -196,8 +199,9 @@ void define_wrapper_functions(py::module &m, const std::string &class_name, cons

m.def(
function_name.c_str(),
[](py::function f, const std::string &name, int d, ioh::common::OptimizationType t, Constraint<T> &c) {
f.dec_ref();
[](py::handle f, const std::string &name, int d, ioh::common::OptimizationType t, Constraint<T> &c) {
f.inc_ref();
WRAPPED_FUNCTIONS.push_back(f);
return wrap_function<T>([f](const std::vector<T> &x) { return PyFloat_AsDouble(f(x).ptr()); }, name, d, t,
c);
},
Expand Down Expand Up @@ -474,9 +478,9 @@ void define_wmodels(py::module &m)
py::arg("ruggedness_gamma") = 0);

py::class_<wmodel::WModelOneMax, WModel, std::shared_ptr<wmodel::WModelOneMax>>(m, "WModelOneMax")
.def(py::init<int, int, double, int, int, int>(),
py::arg("instance"), py::arg("n_variables"), py::arg("dummy_select_rate") = 0.0,
py::arg("epistasis_block_size") = 0, py::arg("neutrality_mu") = 0, py::arg("ruggedness_gamma") = 0);
.def(py::init<int, int, double, int, int, int>(), py::arg("instance"), py::arg("n_variables"),
py::arg("dummy_select_rate") = 0.0, py::arg("epistasis_block_size") = 0, py::arg("neutrality_mu") = 0,
py::arg("ruggedness_gamma") = 0);
}

void define_problem(py::module &m)
Expand All @@ -485,4 +489,10 @@ void define_problem(py::module &m)
define_bbob_problems(m);
define_pbo_problems(m);
define_wmodels(m);

py::module_::import("atexit").attr("register")(py::cpp_function([]() {
for (const auto fn : WRAPPED_FUNCTIONS){
fn.dec_ref();
}
}));
}
27 changes: 27 additions & 0 deletions tests/python/test_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,5 +178,32 @@ def test_file_comparisons(self):
self.assertTrue(math.isclose(p(x), float(y), abs_tol = tol))


def test_wrap_problem_scoped(self):
def w():
l = lambda x: 0.0
p = ioh.problem.wrap_real_problem(l, "l")
return p
p = w()
y = p([0]*5)
self.assertEqual(y, 0.0)

def test_wrap_problem(self):
l = lambda x: 0.0
p = ioh.problem.wrap_real_problem(l, "f")
p([0]*5)

p2 = ioh.problem.wrap_real_problem(l, "f")
self.assertEqual(p.meta_data.problem_id, p2.meta_data.problem_id)
self.assertEqual(p.meta_data.name, p2.meta_data.name)

def test_wrap_problem_builtins(self):
for f in (sum, min, max):
p = ioh.problem.wrap_real_problem(f, "f")
y = p([0]*5)
self.assertEqual(y, 0.0)




if __name__ == "__main__":
unittest.main()

0 comments on commit 4386bc3

Please sign in to comment.