Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ObjSolver #2504

Merged
merged 6 commits into from
May 25, 2023
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
2 changes: 2 additions & 0 deletions libmamba/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ set(LIBMAMBA_SOURCES
${LIBMAMBA_SOURCE_DIR}/solv-cpp/pool.cpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/repo.cpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solvable.cpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solver.cpp
# C++ wrapping of libcurl
${LIBMAMBA_SOURCE_DIR}/core/curl.cpp
# C++ wrapping of compression libs (zstd and bzlib)
Expand Down Expand Up @@ -275,6 +276,7 @@ set(LIBMAMBA_PRIVATE_HEADERS
${LIBMAMBA_SOURCE_DIR}/solv-cpp/ids.hpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/pool.hpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solvable.hpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/solver.hpp
${LIBMAMBA_SOURCE_DIR}/solv-cpp/repo.hpp
# C++ wrapping of compression libs (zstd and bzlib)
${LIBMAMBA_SOURCE_DIR}/core/compression.hpp
Expand Down
3 changes: 3 additions & 0 deletions libmamba/src/solv-cpp/ids.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ namespace mamba::solv
using DependencyId = ::Id;
using RepoId = ::Id;
using SolvableId = ::Id;
using RuleId = ::Id;
using ProblemId = ::Id;

using RelationFlag = int;
using DistType = int;
using SolverFlag = int;
}

#endif
14 changes: 14 additions & 0 deletions libmamba/src/solv-cpp/pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#include <solv/pooltypes.h>
#include <solv/repo.h>
#include <solv/selection.h>
extern "C" // Incomplete header
{
#include <solv/conda.h>
}

#include "solv-cpp/pool.hpp"

Expand Down Expand Up @@ -112,6 +116,16 @@ namespace mamba::solv
return id;
}

auto ObjPool::add_conda_dependency(raw_str_view dep) -> DependencyId
{
return ::pool_conda_matchspec(raw(), dep);
}

auto ObjPool::add_conda_dependency(const std::string& dep) -> DependencyId
{
return add_conda_dependency(dep.c_str());
}

auto ObjPool::get_dependency_name(DependencyId id) const -> std::string_view
{
return ::pool_id2str(raw(), id);
Expand Down
13 changes: 12 additions & 1 deletion libmamba/src/solv-cpp/pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
#include "solv-cpp/repo.hpp"
#include "solv-cpp/solvable.hpp"

using Pool = struct s_Pool;
extern "C"
{
using Pool = struct s_Pool;
}

namespace mamba::solv
{
Expand All @@ -33,6 +36,8 @@ namespace mamba::solv
{
public:

using raw_str_view = const char*;

ObjPool();
~ObjPool();

Expand Down Expand Up @@ -95,6 +100,12 @@ namespace mamba::solv
*/
auto add_dependency(StringId name_id, RelationFlag flag, StringId version_id) -> DependencyId;

/**
* Parse a dependency from string and add it to the pool.
*/
auto add_conda_dependency(raw_str_view dep) -> DependencyId;
auto add_conda_dependency(const std::string& dep) -> DependencyId;

/** Get the registered name of a dependency. */
auto get_dependency_name(DependencyId id) const -> std::string_view;

Expand Down
5 changes: 4 additions & 1 deletion libmamba/src/solv-cpp/repo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
#include "solv-cpp/ids.hpp"
#include "solv-cpp/solvable.hpp"

using Repo = struct s_Repo;
extern "C"
{
using Repo = struct s_Repo;
}

namespace fs
{
Expand Down
5 changes: 4 additions & 1 deletion libmamba/src/solv-cpp/solvable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
#include "solv-cpp/ids.hpp"
#include "solv-cpp/queue.hpp"

using Solvable = struct s_Solvable;
extern "C"
{
using Solvable = struct s_Solvable;
}

namespace mamba::solv
{
Expand Down
115 changes: 115 additions & 0 deletions libmamba/src/solv-cpp/solver.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) 2023, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#include <cassert>

#include <solv/poolid.h>
#include <solv/solvable.h>
#include <solv/solver.h>
// broken headers go last
#include <solv/problems.h>
#include <solv/rules.h>

#include "solv-cpp/pool.hpp"
#include "solv-cpp/queue.hpp"
#include "solv-cpp/solver.hpp"

namespace mamba::solv
{
void ObjSolver::SolverDeleter::operator()(::Solver* ptr)
{
::solver_free(ptr);
}

ObjSolver::ObjSolver(const ObjPool& pool)
: m_solver(::solver_create(const_cast<::Pool*>(pool.raw())))
{
}

ObjSolver::~ObjSolver() = default;

auto ObjSolver::raw() -> ::Solver*
{
return m_solver.get();
}

void ObjSolver::set_flag(SolverFlag flag, bool value)
{
::solver_set_flag(raw(), flag, value);
}

auto ObjSolver::get_flag(SolverFlag flag) const -> bool
{
const auto val = ::solver_get_flag(const_cast<::Solver*>(raw()), flag);
assert((val == 0) || (val == 1));
return val != 0;
}

auto ObjSolver::raw() const -> const ::Solver*
{
return m_solver.get();
}

auto ObjSolver::solve(const ObjPool& /* pool */, const ObjQueue& jobs) -> bool
{
// pool is captured inside solver so we take it as a parameter to be explicit.
const auto n_pbs = ::solver_solve(raw(), const_cast<::Queue*>(jobs.raw()));
return n_pbs == 0;
}

auto ObjSolver::problem_count() const -> std::size_t
{
return ::solver_problem_count(const_cast<::Solver*>(raw()));
}

auto ObjSolver::problem_to_string(const ObjPool& /* pool */, ProblemId id) const -> std::string
{
// pool is captured inside solver so we take it as a parameter to be explicit.
return ::solver_problem2str(const_cast<::Solver*>(raw()), id);
}

auto ObjSolver::next_problem(ProblemId id) const -> ProblemId
{
return ::solver_next_problem(const_cast<::Solver*>(raw()), id);
}

auto ObjSolver::problem_rules(ProblemId id) const -> ObjQueue
{
ObjQueue rules = {};
::solver_findallproblemrules(const_cast<::Solver*>(raw()), id, rules.raw());
return rules;
}

auto ObjSolver::get_rule_info(const ObjPool& /* pool */, RuleId id) const -> ObjRuleInfo
{
// pool is captured inside solver so we take it as a parameter to be explicit.
SolvableId from_id = 0;
SolvableId to_id = 0;
DependencyId dep_id = 0;
const auto type = ::solver_ruleinfo(const_cast<::Solver*>(raw()), id, &from_id, &to_id, &dep_id);

return {
/* .from_id= */ (from_id != 0) ? std::optional{ from_id } : std::nullopt,
/* .to_id= */ (to_id != 0) ? std::optional{ to_id } : std::nullopt,
/* .dep_id= */ (dep_id != 0) ? std::optional{ dep_id } : std::nullopt,
/* .type= */ type,
/* .klass= */ ::solver_ruleclass(const_cast<::Solver*>(raw()), id),
};
}

auto ObjSolver::rule_info_to_string(const ObjPool& /* pool */, ObjRuleInfo ri) const -> std::string
{
// pool is captured inside solver so we take it as a parameter to be explicit.
return ::solver_ruleinfo2str(
const_cast<::Solver*>(raw()),
ri.type,
ri.from_id.value_or(0),
ri.to_id.value_or(0),
ri.dep_id.value_or(0)
);
}

}
101 changes: 101 additions & 0 deletions libmamba/src/solv-cpp/solver.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright (c) 2023, QuantStack and Mamba Contributors
//
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.

#ifndef MAMBA_SOLV_SOLVER_HPP
#define MAMBA_SOLV_SOLVER_HPP

#include <memory>
#include <optional>
#include <string>

// START Only required for broken header <solv/rule.h>
#include <solv/poolid.h>
extern "C"
{
typedef struct s_Solvable Solvable;
typedef struct s_Map Map;
typedef struct s_Queue Queue;
}
// END
#include <solv/rules.h>

#include "solv-cpp/ids.hpp"
#include "solv-cpp/queue.hpp"

extern "C"
{
using Solver = struct s_Solver;
}

namespace mamba::solv
{
class ObjPool;
class ObjQueue;

struct ObjRuleInfo
{
std::optional<SolvableId> from_id;
std::optional<SolvableId> to_id;
std::optional<DependencyId> dep_id;
::SolverRuleinfo type;
::SolverRuleinfo klass;
};

class ObjSolver
{
public:

ObjSolver(const ObjPool& pool);
~ObjSolver();

auto raw() -> ::Solver*;
auto raw() const -> const ::Solver*;

void set_flag(SolverFlag flag, bool value);
[[nodiscard]] auto get_flag(SolverFlag flag) const -> bool;

[[nodiscard]] auto solve(const ObjPool& pool, const ObjQueue& jobs) -> bool;

[[nodiscard]] auto problem_count() const -> std::size_t;
[[nodiscard]] auto problem_to_string(const ObjPool& pool, ProblemId id) const -> std::string;
template <typename UnaryFunc>
void for_each_problem_id(UnaryFunc&& func) const;

/**
* Return an @ref ObjQueue of @ref RuleId with all rules involved in a current problem.
*/
[[nodiscard]] auto problem_rules(ProblemId id) const -> ObjQueue;
[[nodiscard]] auto get_rule_info(const ObjPool& pool, RuleId id) const -> ObjRuleInfo;
[[nodiscard]] auto rule_info_to_string(const ObjPool& pool, ObjRuleInfo id) const
-> std::string;

private:

struct SolverDeleter
{
void operator()(::Solver* ptr);
};

std::unique_ptr<::Solver, ObjSolver::SolverDeleter> m_solver = nullptr;

auto next_problem(ProblemId id = 0) const -> ProblemId;
};

/*********************************
* Implementation of ObjSolver *
*********************************/

template <typename UnaryFunc>
void ObjSolver::for_each_problem_id(UnaryFunc&& func) const
{
for (ProblemId id = next_problem(); id != 0; id = next_problem(id))
{
func(id);
}
}

}
#endif
1 change: 1 addition & 0 deletions libmamba/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ set(LIBMAMBA_TEST_SRCS
src/solv-cpp/test_pool.cpp
src/solv-cpp/test_repo.cpp
src/solv-cpp/test_solvable.cpp
src/solv-cpp/test_solver.cpp
# Utility library
src/util/test_flat_set.cpp
src/util/test_graph.cpp
Expand Down
7 changes: 7 additions & 0 deletions libmamba/tests/src/solv-cpp/test_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ TEST_SUITE("ObjPool")
CHECK_EQ(pool.get_dependency_relation(id_rel), " > ");
CHECK_EQ(pool.get_dependency_version(id_rel), "1.0.0");
CHECK_EQ(pool.dependency_to_string(id_rel), "mamba > 1.0.0");

SUBCASE("Parse a conda dependency")
{
const auto id_conda = pool.add_conda_dependency("rattler < 0.1");
CHECK_EQ(pool.get_dependency_name(id_conda), "rattler");
CHECK_EQ(pool.get_dependency_version(id_conda), "<0.1");
}
}

SUBCASE("Add repo")
Expand Down
Loading