Skip to content

Commit a85f186

Browse files
committed
Overload 'bdd_satmin' and 'bdd_satmax' with symbolic set of variables
1 parent 0ecd02c commit a85f186

File tree

4 files changed

+334
-6
lines changed

4 files changed

+334
-6
lines changed

src/adiar/bdd.h

+34
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,23 @@ namespace adiar
13811381
return bdd_satmin(f, make_generator(cbegin, cend), std::distance(cbegin, cend));
13821382
}
13831383

1384+
//////////////////////////////////////////////////////////////////////////////////////////////////
1385+
/// \brief The lexicographically smallest x such that f(x) is true.
1386+
///
1387+
/// \param f
1388+
/// BDD of interest.
1389+
///
1390+
/// \param d
1391+
/// BDD cube of variables that ought to be included.
1392+
///
1393+
/// \returns A bdd whos only path to the `true` terminal reflects the minimal assignment.
1394+
///
1395+
/// \throws domain_error
1396+
/// If `bdd_iscube(d)` is not satisfied.
1397+
//////////////////////////////////////////////////////////////////////////////////////////////////
1398+
bdd
1399+
bdd_satmin(const bdd& f, const bdd& d);
1400+
13841401
//////////////////////////////////////////////////////////////////////////////////////////////////
13851402
/// \brief The lexicographically smallest x such that f(x) is true.
13861403
///
@@ -1466,6 +1483,23 @@ namespace adiar
14661483
return bdd_satmax(f, make_generator(cbegin, cend), std::distance(cbegin, cend));
14671484
}
14681485

1486+
//////////////////////////////////////////////////////////////////////////////////////////////////
1487+
/// \brief The lexicographically largest x such that f(x) is true.
1488+
///
1489+
/// \param f
1490+
/// BDD of interest.
1491+
///
1492+
/// \param d
1493+
/// BDD cube of variables that ought to be included.
1494+
///
1495+
/// \returns A bdd whos only path to the `true` terminal reflects the minimal assignment.
1496+
///
1497+
/// \throws domain_error
1498+
/// If `bdd_iscube(d)` is not satisfied.
1499+
//////////////////////////////////////////////////////////////////////////////////////////////////
1500+
bdd
1501+
bdd_satmax(const bdd& f, const bdd& d);
1502+
14691503
//////////////////////////////////////////////////////////////////////////////////////////////////
14701504
/// \brief The lexicographically largest x such that f(x) is true.
14711505
///

src/adiar/bdd/evaluate.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,19 @@ namespace adiar
297297
return __bdd_satX<internal::traverse_satmin_visitor>(f, d, total_levels);
298298
}
299299

300+
bdd
301+
bdd_satmin(const bdd& f, const bdd& d)
302+
{
303+
if (!bdd_iscube(d)) { throw domain_error("BDD 'd' is not a cube"); }
304+
305+
typename internal::level_stream_t<bdd>::template stream_t<> d_levels(d);
306+
const generator<bdd::label_type> d_gen = make_generator__levels(d_levels);
307+
308+
const size_t total_levels = std::min<size_t>(f->levels() + d->levels(), bdd::max_label+1);
309+
310+
return __bdd_satX<internal::traverse_satmin_visitor>(f, d_gen, total_levels);
311+
}
312+
300313
void
301314
bdd_satmin(const bdd& f, const consumer<pair<bdd::label_type, bool>>& c)
302315
{
@@ -316,6 +329,19 @@ namespace adiar
316329
return __bdd_satX<internal::traverse_satmax_visitor>(f, d, total_levels);
317330
}
318331

332+
bdd
333+
bdd_satmax(const bdd& f, const bdd& d)
334+
{
335+
if (!bdd_iscube(d)) { throw domain_error("BDD 'd' is not a cube"); }
336+
337+
typename internal::level_stream_t<bdd>::template stream_t<> d_levels(d);
338+
const generator<bdd::label_type> d_gen = make_generator__levels(d_levels);
339+
340+
const size_t total_levels = std::min<size_t>(f->levels() + d->levels(), bdd::max_label+1);
341+
342+
return __bdd_satX<internal::traverse_satmax_visitor>(f, d_gen, total_levels);
343+
}
344+
319345
void
320346
bdd_satmax(const bdd& f, const consumer<pair<bdd::label_type, bool>>& c)
321347
{

src/adiar/internal/util.h

+24-6
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,42 @@ namespace adiar::internal
4040
template <typename File>
4141
struct level_stream_t
4242
{
43-
template <bool reverse = false>
44-
using stream_t = level_info_stream<reverse>;
43+
template <bool Reverse = false>
44+
using stream_t = level_info_stream<Reverse>;
4545
};
4646

4747
template <>
4848
struct level_stream_t<file<ptr_uint64::label_type>>
4949
{
50-
template <bool reverse = false>
51-
using stream_t = file_stream<ptr_uint64::label_type, reverse>;
50+
template <bool Reverse = false>
51+
using stream_t = file_stream<ptr_uint64::label_type, Reverse>;
5252
};
5353

5454
template <>
5555
struct level_stream_t<shared_file<ptr_uint64::label_type>>
5656
{
57-
template <bool reverse = false>
58-
using stream_t = file_stream<ptr_uint64::label_type, reverse>;
57+
template <bool Reverse = false>
58+
using stream_t = file_stream<ptr_uint64::label_type, Reverse>;
5959
};
6060

61+
//////////////////////////////////////////////////////////////////////////////////////////////////
62+
/// \brief Turn a `level_stream<...>` into a level-only generator function.
63+
///
64+
/// \remark The direction (*ascending* vs. *descending*) of the generator is dictated by the given
65+
/// stream's direction.
66+
///
67+
/// \see level_stream_t, generator
68+
//////////////////////////////////////////////////////////////////////////////////////////////////
69+
template <typename LevelStream>
70+
generator<ptr_uint64::label_type>
71+
make_generator__levels(LevelStream& ls)
72+
{
73+
return [&ls]() mutable -> optional<ptr_uint64::label_type> {
74+
if (!ls.can_pull()) { return {}; }
75+
return level_of(ls.pull());
76+
};
77+
}
78+
6179
//////////////////////////////////////////////////////////////////////////////////////////////////
6280
/// \brief Obtain whether the levels in two files are disjoint.
6381
//////////////////////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)