Skip to content

Commit f5679bf

Browse files
Implement basic_solver and resolver classes with flaw management and enum handling
1 parent 7b6d7b5 commit f5679bf

5 files changed

Lines changed: 173 additions & 5 deletions

File tree

include/basic_solver.hpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,132 @@
22

33
#include "solver_core.hpp"
44

5+
#ifdef ORATIO_ENABLE_LISTENERS
6+
#define NEW_FLAW(f) flaw_created(f)
7+
#define NEW_RESOLVER(r) resolver_created(r)
8+
#else
9+
#define NEW_FLAW(f)
10+
#define NEW_RESOLVER(r)
11+
#endif
12+
513
namespace ratio
614
{
15+
class basic_solver;
16+
class resolver;
17+
18+
class flaw
19+
{
20+
public:
21+
flaw(basic_solver &slv) noexcept;
22+
flaw(const flaw &) = delete;
23+
virtual ~flaw() = default;
24+
25+
private:
26+
virtual void compute_resolvers() = 0;
27+
28+
protected:
29+
basic_solver &slv; // The solver managing this flaw..
30+
};
31+
32+
class resolver
33+
{
34+
public:
35+
resolver(flaw &flw, utils::rational &&intrinsic_cost) noexcept;
36+
resolver(const resolver &) = delete;
37+
virtual ~resolver() = default;
38+
39+
private:
40+
virtual void apply() = 0;
41+
42+
protected:
43+
flaw &flw; // The flaw this resolver addresses..
44+
utils::rational intrinsic_cost; // The intrinsic cost of applying this resolver..
45+
};
46+
747
class basic_solver : public solver_core
848
{
949
public:
1050
basic_solver() noexcept;
1151

52+
[[nodiscard]] riddle::expr new_enum(riddle::component_type &tp, std::vector<riddle::expr> &&values) override;
53+
54+
/**
55+
* @brief Creates a new flaw of the given type.
56+
*
57+
* @tparam Tp The type of the flaw to create.
58+
* @tparam Args The types of the arguments to pass to the flaw
59+
* @param args The arguments to pass to the flaw
60+
* @return Tp& The created flaw
61+
*/
62+
template <typename Tp, typename... Args>
63+
Tp &new_flaw(Args &&...args) noexcept
64+
{
65+
static_assert(std::is_base_of_v<flaw, Tp>, "Tp must be a subclass of flaw");
66+
auto f = std::make_unique<Tp>(std::forward<Args>(args)...);
67+
auto &f_ref = *f;
68+
NEW_FLAW(f_ref);
69+
flaws.emplace_back(std::move(f));
70+
return f_ref;
71+
}
72+
73+
/**
74+
* @brief Creates a new resolver of the given type.
75+
*
76+
* @tparam Tp The type of the resolver to create.
77+
* @tparam Args The types of the arguments to pass to the resolver
78+
* @param args The arguments to pass to the resolver
79+
* @return Tp& The created resolver
80+
*/
81+
template <typename Tp, typename... Args>
82+
Tp &new_resolver(Args &&...args) noexcept
83+
{
84+
static_assert(std::is_base_of_v<resolver, Tp>, "Tp must be a subclass of resolver");
85+
auto r = std::make_unique<Tp>(std::forward<Args>(args)...);
86+
auto &r_ref = *r;
87+
NEW_RESOLVER(r_ref);
88+
resolvers.emplace_back(std::move(r));
89+
return r_ref;
90+
}
91+
1292
void solve() override;
93+
94+
#ifdef ORATIO_ENABLE_LISTENERS
95+
private:
96+
/**
97+
* @brief Notifies that a new flaw has been created.
98+
*
99+
* This function is called whenever a new flaw is created in the solver.
100+
*
101+
* @param f The newly created flaw.
102+
*/
103+
virtual void flaw_created([[maybe_unused]] flaw &f) noexcept {}
104+
105+
/**
106+
* @brief Notifies that a new resolver has been created.
107+
*
108+
* This function is called whenever a new resolver is created in the solver.
109+
*
110+
* @param r The newly created resolver.
111+
*/
112+
virtual void resolver_created([[maybe_unused]] resolver &r) noexcept {}
113+
#endif
114+
115+
private:
116+
std::vector<std::unique_ptr<flaw>> flaws; // The set of flaws
117+
std::vector<std::unique_ptr<resolver>> resolvers; // The set of resolvers
118+
};
119+
120+
class enum_flaw final : public flaw
121+
{
122+
public:
123+
enum_flaw(basic_solver &slv, riddle::enum_expr var) noexcept;
124+
125+
[[nodiscard]] const riddle::enum_expr &get_var() const noexcept { return var; }
126+
127+
private:
128+
void compute_resolvers() override;
129+
130+
private:
131+
riddle::enum_expr var;
13132
};
14133
} // namespace ratio

include/solver_core.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ namespace ratio
3434
[[nodiscard]] riddle::string_expr new_string(std::string &&value) override;
3535
[[nodiscard]] std::string string_value(const riddle::string_term &expr) const noexcept override;
3636

37-
[[nodiscard]] riddle::expr new_enum(riddle::component_type &tp, std::vector<riddle::expr> &&values) override;
3837
[[nodiscard]] std::vector<riddle::expr> enum_value(const riddle::enum_term &expr) const noexcept override;
3938

4039
[[nodiscard]] riddle::arith_expr new_negation(riddle::arith_expr xpr) override;
@@ -53,8 +52,8 @@ namespace ratio
5352
[[nodiscard]] riddle::atom_expr create_atom(bool is_fact, riddle::predicate &pred, std::map<std::string, riddle::expr, std::less<>> &&args) override;
5453
[[nodiscard]] riddle::atom_state get_atom_state(const riddle::atom_term &atom) const noexcept override;
5554

56-
private:
55+
protected:
5756
arc_consistency::solver ac_slv; // The arc consistency solver..
58-
linspire::solver lin_slv;
57+
linspire::solver lin_slv; // The linear programming solver..
5958
};
6059
} // namespace ratio

src/basic_solver.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,39 @@
1-
#include "basic_solver.hpp"
1+
#include "basic_solver.hpp"
2+
#include "items.hpp"
3+
#include "logging.hpp"
4+
#include <cassert>
5+
6+
namespace ratio
7+
{
8+
flaw::flaw(basic_solver &slv) noexcept : slv(slv) {}
9+
10+
resolver::resolver(flaw &flw, utils::rational &&intrinsic_cost) noexcept : flw(flw), intrinsic_cost(std::move(intrinsic_cost)) {}
11+
12+
basic_solver::basic_solver() noexcept : solver_core("oRatio Basic Solver") {}
13+
14+
riddle::expr basic_solver::new_enum(riddle::component_type &tp, std::vector<riddle::expr> &&values)
15+
{
16+
assert(!values.empty());
17+
if (values.size() == 1)
18+
{ // Single-valued enum
19+
assert(&values.front()->get_type() == &tp);
20+
return values.front();
21+
}
22+
else
23+
{
24+
std::vector<std::reference_wrapper<const utils::enum_val>> ev_refs;
25+
for (auto &ev_ptr : values)
26+
ev_refs.emplace_back(*ev_ptr);
27+
auto ev = ac_slv.new_var(ev_refs);
28+
// .. and create a new enum flaw to manage the variable..
29+
auto &ef = new_flaw<enum_flaw>(*this, std::make_shared<riddle::enum_item>(tp, std::move(values), ev));
30+
return ef.get_var();
31+
}
32+
}
33+
34+
void basic_solver::solve() {}
35+
36+
enum_flaw::enum_flaw(basic_solver &slv, riddle::enum_expr var) noexcept : flaw(slv), var(std::move(var)) {}
37+
38+
void enum_flaw::compute_resolvers() {}
39+
} // namespace ratio

src/solver_core.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "solver_core.hpp"
22
#include "items.hpp"
3+
#include "logging.hpp"
4+
#include <cassert>
35

46
namespace ratio
57
{
@@ -31,4 +33,14 @@ namespace ratio
3133
riddle::string_expr solver_core::new_string() { return std::make_shared<riddle::string_item>(static_cast<riddle::string_type &>(get_type(riddle::string_kw)), ""); }
3234
riddle::string_expr solver_core::new_string(std::string &&value) { return std::make_shared<riddle::string_item>(static_cast<riddle::string_type &>(get_type(riddle::string_kw)), std::move(value)); }
3335
std::string solver_core::string_value(const riddle::string_term &expr) const noexcept { return static_cast<const riddle::string_item &>(expr).get_string(); }
36+
37+
std::vector<riddle::expr> solver_core::enum_value(const riddle::enum_term &expr) const noexcept
38+
{
39+
auto &dom = ac_slv.domain(static_cast<const riddle::enum_item &>(expr).get_var());
40+
std::vector<riddle::expr> values;
41+
for (auto ev_ptr : static_cast<const riddle::enum_item &>(expr).get_values())
42+
if (dom.find(&*ev_ptr) != dom.end())
43+
values.push_back(ev_ptr);
44+
return values;
45+
};
3446
} // namespace ratio

0 commit comments

Comments
 (0)