Skip to content

Commit

Permalink
Clean 'dd_varprofile' API to use consumers/iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
SSoelvsten committed Sep 24, 2023
1 parent 3265fa1 commit 7a3ce0e
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 67 deletions.
37 changes: 27 additions & 10 deletions src/adiar/bdd.h
Original file line number Diff line number Diff line change
Expand Up @@ -829,20 +829,37 @@ namespace adiar
const shared_file<map_pair<bdd::label_t, boolean>> &xs);

//////////////////////////////////////////////////////////////////////////////
/// \brief Get the labels of the levels of the BDD
/// \brief Get the labels of the levels of the BDD.
///
/// \param f BDD of interest.
///
/// \param cb Callback function that consumes the levels (in ascending order).
//////////////////////////////////////////////////////////////////////////////
shared_file<bdd::label_t> bdd_varprofile(const bdd &f);
void bdd_varprofile(const bdd &f, const std::function<void(bdd::label_t)> &cb);

//////////////////////////////////////////////////////////////////////////////
// TODO: add callback
//
// bdd_varprofile(const bdd &f, const std::function<void(bdd::label_t)> &cb);

/// \brief Write the labels of the BDD's levels into the given container.
///
/// \param f BDD of interest.
///
/// \param begin Iterator for the beginning to place the output.
///
/// \param end Iterator that marks the end for `begin`.
///
/// \returns An iterator to the first entry that still is left empty.
///
/// \throws out_of_range If the distance between `begin` and `end` is not big
/// enough to contain all variables in `f`.
//////////////////////////////////////////////////////////////////////////////
// TODO: wrap into consumer lambda
//
// template<typename IT>
// bdd_varprofile(const bdd &f, IT begin, IT end)
template<typename IT>
IT bdd_varprofile(const bdd &f, IT begin, IT end)
{
if (std::distance(begin, end) < bdd_varcount(f)) {
throw std::out_of_range("Distance between 'begin' and 'end' too small");
}
bdd_varprofile(f, internal::iterator_consumer<bdd::label_t>(begin, end));
return begin;
}

/// \}
//////////////////////////////////////////////////////////////////////////////
Expand Down
4 changes: 2 additions & 2 deletions src/adiar/bdd/bdd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ namespace adiar

//////////////////////////////////////////////////////////////////////////////
// Input variables
shared_file<bdd::label_t> bdd_varprofile(const bdd &f)
void bdd_varprofile(const bdd &f, const std::function<void(bdd::label_t)> &cb)
{
return internal::dd_varprofile(f);
return internal::dd_varprofile(f, cb);
}

//////////////////////////////////////////////////////////////////////////////
Expand Down
9 changes: 8 additions & 1 deletion src/adiar/internal/algorithms/intercut.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,14 @@ namespace adiar::internal
shared_levelized_file<arc> out_arcs;
arc_writer aw(out_arcs);

shared_file<typename intercut_policy::label_t> dd_levels = dd_varprofile(dd);
shared_file<typename intercut_policy::label_t> dd_levels;
{
file_writer<typename intercut_policy::label_t> lw(dd_levels);
dd_varprofile(dd, [&lw](const typename intercut_policy::label_t x) {
lw << x;
});
}

pq_t intercut_pq({dd_levels, labels}, pq_memory, max_pq_size, stats_intercut.lpq);

// Add request for root in the queue
Expand Down
13 changes: 3 additions & 10 deletions src/adiar/internal/dd_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,11 @@ namespace adiar::internal
/// \brief Obtain the level_info stream projected onto the labels.
////////////////////////////////////////////////////////////////////////////
template <typename dd_t>
inline shared_file<typename dd_t::label_t>
dd_varprofile(const dd_t &dd)
void dd_varprofile(const dd_t &dd,
const std::function<void(typename dd_t::label_t)> &cb)
{
level_info_stream<> info_stream(dd);

shared_file<typename dd_t::label_t> vars;
file_writer<typename dd_t::label_t> writer(vars);

while(info_stream.can_pull()) {
writer << info_stream.pull().label();
}
return vars;
while(info_stream.can_pull()) { cb(info_stream.pull().label()); }
}

// TODO: move into 'dd' class?
Expand Down
16 changes: 16 additions & 0 deletions src/adiar/internal/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,22 @@ namespace adiar::internal
};
}

////////////////////////////////////////////////////////////////////////////
/// \brief Converts a `begin` and `end` iterator pair into a consumer
/// function.
////////////////////////////////////////////////////////////////////////////
template<typename label_t, typename IT>
inline std::function<void(label_t)>
iterator_consumer(IT &begin, IT &end)
{
return [&begin, &end](const label_t x) {
adiar_assert(begin != end,
"Missing initial check for std::distance(begin, end)?");

*(begin++) = x;
};
}

////////////////////////////////////////////////////////////////////////////
/// \brief Converts a `file_stream` into a generator function.
////////////////////////////////////////////////////////////////////////////
Expand Down
37 changes: 27 additions & 10 deletions src/adiar/zdd.h
Original file line number Diff line number Diff line change
Expand Up @@ -729,20 +729,37 @@ namespace adiar
// zdd_maxelem(const zdd &A, IT begin, IT end)

//////////////////////////////////////////////////////////////////////////////
/// \brief Get the labels of the levels of the ZDD
/// \brief Get the labels of the levels of the ZDD.
///
/// \param A ZDD of interest.
///
/// \param cb Callback function that consumes the levels (in ascending order).
//////////////////////////////////////////////////////////////////////////////
shared_file<zdd::label_t> zdd_varprofile(const zdd &A);
void zdd_varprofile(const zdd &A, const std::function<void(zdd::label_t)> &cb);

//////////////////////////////////////////////////////////////////////////////
// TODO: add callback
//
// zdd_varprofile(const zdd &A, const std::function<void(zdd::label_t)> &cb);

/// \brief Write the labels of the ZDD's levels into the given container.
///
/// \param A ZDD of interest.
///
/// \param begin Iterator for the beginning to place the output.
///
/// \param end Iterator that marks the end for `begin`.
///
/// \returns An iterator to the first entry that still is left empty.
///
/// \throws out_of_range If the distance between `begin` and `end` is not big
/// enough to contain all variables in `f`.
//////////////////////////////////////////////////////////////////////////////
// TODO: wrap into consumer lambda
//
// template<typename IT>
// zdd_varprofile(const zdd &A, IT begin, IT end)
template<typename IT>
IT zdd_varprofile(const zdd &A, IT begin, IT end)
{
if (std::distance(begin, end) < zdd_varcount(A)) {
throw std::out_of_range("Distance between 'begin' and 'end' too small");
}
zdd_varprofile(A, internal::iterator_consumer<bdd::label_t>(begin, end));
return begin;
}

/// \}
//////////////////////////////////////////////////////////////////////////////
Expand Down
4 changes: 2 additions & 2 deletions src/adiar/zdd/zdd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,9 @@ namespace adiar

//////////////////////////////////////////////////////////////////////////////
// Input variables
shared_file<zdd::label_t> zdd_varprofile(const zdd &A)
void zdd_varprofile(const zdd &A, const std::function<void(zdd::label_t)> &cb)
{
return internal::dd_varprofile(A);
return internal::dd_varprofile(A, cb);
}

//////////////////////////////////////////////////////////////////////////////
Expand Down
87 changes: 55 additions & 32 deletions test/adiar/internal/test_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

go_bandit([]() {
describe("adiar/internal/util.h", []() {
describe("dd_varprofile", []() {
describe("dd_varprofile(f, cb)", []() {
// TODO
});

describe("dd_varprofile(f, begin, end)", []() {
shared_levelized_file<node> terminal_F;
{
node_writer writer(terminal_F);
Expand Down Expand Up @@ -43,64 +47,83 @@ go_bandit([]() {
writer << n4 << n3 << n2 << n1;
}

it("returns empty file for a BDD false terminal", [&]() {
adiar::shared_file<bdd::label_t> label_file_out = bdd_varprofile(terminal_F);
it("does not write anything for BDD false terminal", [&]() {
std::vector<int> out(42, -1);

auto it_b = out.begin();
auto it_e = out.end();

adiar::file_stream<bdd::label_t> out_labels(label_file_out);
const auto out_it = bdd_varprofile(terminal_F, it_b, it_e);

AssertThat(out_labels.can_pull(), Is().False());
AssertThat(out_it, Is().EqualTo(it_b));
AssertThat(*it_b, Is().EqualTo(-1));
});

it("returns empty file for a ZDD true terminal", [&]() {
adiar::shared_file<zdd::label_t> label_file_out = zdd_varprofile(terminal_T);
std::vector<int> out(42, -1);

adiar::file_stream<zdd::label_t> out_labels(label_file_out);
auto it_b = out.begin();
auto it_e = out.end();

AssertThat(out_labels.can_pull(), Is().False());
const auto out_it = zdd_varprofile(terminal_T, it_b, it_e);

AssertThat(out_it, Is().EqualTo(it_b));
AssertThat(*it_b, Is().EqualTo(-1));
});

it("returns [42] for a ZDD with one node (label 42)", [&]() {
adiar::shared_file<zdd::label_t> label_file_out = zdd_varprofile(x42);
std::vector<int> out(42, -1);

auto it_b = out.begin();
auto it_e = out.end();

adiar::file_stream<zdd::label_t> out_labels(label_file_out);
const auto out_it = zdd_varprofile(x42, it_b, it_e);

AssertThat(out_labels.can_pull(), Is().True());
AssertThat(out_labels.pull(), Is().EqualTo(42u));
AssertThat(out_labels.can_pull(), Is().False());
AssertThat(out_it, Is().EqualTo(it_b+1));
AssertThat(*it_b, Is().EqualTo(42));
AssertThat(*out_it, Is().EqualTo(-1));
});

it("returns [1,3,4] for a BDD with multiple nodes", [&]() {
adiar::shared_file<bdd::label_t> label_file_out = bdd_varprofile(bdd_file);
std::vector<int> out(42, -1);

adiar::file_stream<bdd::label_t> out_labels(label_file_out);
auto it_b = out.begin();
auto it_e = out.end();

AssertThat(out_labels.can_pull(), Is().True());
AssertThat(out_labels.pull(), Is().EqualTo(1u));
const auto out_it = bdd_varprofile(bdd_file, it_b, it_e);

AssertThat(out_labels.can_pull(), Is().True());
AssertThat(out_labels.pull(), Is().EqualTo(3u));
AssertThat(*(it_b+0), Is().EqualTo(1));
AssertThat(*(it_b+1), Is().EqualTo(3));
AssertThat(*(it_b+2), Is().EqualTo(4));

AssertThat(out_labels.can_pull(), Is().True());
AssertThat(out_labels.pull(), Is().EqualTo(4u));

AssertThat(out_labels.can_pull(), Is().False());
AssertThat(out_it, Is().EqualTo(it_b+3));
AssertThat(*out_it, Is().EqualTo(-1));
});

it("returns [0,1,2] for a ZDD with multiple nodes", [&]() {
adiar::shared_file<zdd::label_t> label_file_out = zdd_varprofile(zdd_file);
std::vector<int> out(42, -1);

auto it_b = out.begin();
auto it_e = out.end();

adiar::file_stream<zdd::label_t> out_labels(label_file_out);
const auto out_it = zdd_varprofile(zdd_file, it_b, it_e);

AssertThat(out_labels.can_pull(), Is().True());
AssertThat(out_labels.pull(), Is().EqualTo(0u));
AssertThat(*(it_b+0), Is().EqualTo(0));
AssertThat(*(it_b+1), Is().EqualTo(1));
AssertThat(*(it_b+2), Is().EqualTo(2));

AssertThat(out_labels.can_pull(), Is().True());
AssertThat(out_labels.pull(), Is().EqualTo(1u));
AssertThat(out_it, Is().EqualTo(it_b+3));
AssertThat(*out_it, Is().EqualTo(-1));
});

AssertThat(out_labels.can_pull(), Is().True());
AssertThat(out_labels.pull(), Is().EqualTo(2u));
it("throws if range is too small for BDD", [&]() {
std::vector<int> out(1,-1);
AssertThrows(out_of_range, bdd_varprofile(bdd_file, out.begin(), out.end()));
});

AssertThat(out_labels.can_pull(), Is().False());
it("throws if range is too small for ZDD", [&]() {
std::vector<int> out(1,-1);
AssertThrows(out_of_range, zdd_varprofile(zdd_file, out.begin(), out.end()));
});
});

Expand Down

0 comments on commit 7a3ce0e

Please sign in to comment.