Skip to content

Commit

Permalink
Corrected min reachable
Browse files Browse the repository at this point in the history
  • Loading branch information
Kalashnikovni committed Jan 9, 2024
1 parent b8518fa commit c7b4c65
Show file tree
Hide file tree
Showing 18 changed files with 181 additions and 134 deletions.
2 changes: 1 addition & 1 deletion eval/defs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ FuncEnv::FuncEnv() {}
FuncEnvType FuncEnv::mapping_ = {{"isEmpty", 0}, {"isMember", 1}, {"minElem", 2}, {"maxElem", 3}, {"lt", 4},
{"compose", 5}, {"inv", 6}, {"image", 7}, {"preImage", 8}, {"dom", 9}, {"combine", 10}, {"minMap", 11},
{"reduce", 12}, {"minAdj", 13}, {"CC", 14}, {"minReach", 15}, {"matching", 16}, {"scc", 17},
{"sort", 18}};
{"sort", 18}, {"firstInv", 19}};

MaybeFValue FuncEnv::operator[](FKey k) const
{
Expand Down
2 changes: 1 addition & 1 deletion eval/defs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ struct FuncEnv{
};

typedef enum { empty, member, min, max, lt, comp, inv, im, preim, dom, comb, min_map, red, min_adj
, connected, min_reach, matching, scc, ts } Func;
, connected, min_reach, matching, scc, ts, first_inv } Func;

// Classes for pretty printing ------------------------------------------------

Expand Down
87 changes: 32 additions & 55 deletions eval/visitors/eval_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,28 +85,6 @@ auto compose_map_visitor_ = Util::Overload {
}
};

/*
auto inverse_visitor_ = Util::Overload {
[](LIB::LExp a) { return LinearBaseType(a.inverse()); },
[](LIB::Exp a) { return LinearBaseType(a.inverse()); },
[](auto a) {
Util::ERROR("Wrong arguments for inversion");
return ExprBaseType();
}
};
auto image_visitor1_ = Util::Overload {
[](LIB::BaseMap a) { return ContainerBaseType(a.image()); },
[](LIB::CanonMap a) { return ContainerBaseType(a.image()); },
[](LIB::BasePWMap a) { return ContainerBaseType(a.image()); },
[](LIB::CanonPWMap a) { return ContainerBaseType(a.image()); },
[](auto a) {
Util::ERROR("Wrong arguments for image 1");
return ExprBaseType();
}
};
*/

auto image_visitor2_ = Util::Overload {
[](LIB::UnordSet a, LIB::BaseMap b) { return ContainerBaseType(b.image(a)); },
[](LIB::OrdSet a, LIB::CanonMap b) { return ContainerBaseType(b.image(a)); },
Expand All @@ -122,19 +100,6 @@ auto image_visitor2_ = Util::Overload {
}
};

/*
auto pre_image_visitor1_ = Util::Overload {
[](LIB::BaseMap a) { return ContainerBaseType(a.preImage()); },
[](LIB::CanonMap a) { return ContainerBaseType(a.preImage()); },
[](LIB::BasePWMap a) { return ContainerBaseType(a.preImage()); },
[](LIB::CanonPWMap a) { return ContainerBaseType(a.preImage()); },
[](auto a) {
Util::ERROR("Wrong arguments for pre image 1");
return ExprBaseType();
}
};
*/

auto pre_image_visitor2_ = Util::Overload {
[](LIB::UnordSet a, LIB::BaseMap b) {
return ContainerBaseType(b.preImage(a));
Expand All @@ -154,17 +119,6 @@ auto pre_image_visitor2_ = Util::Overload {
}
};

/*
auto dom_visitor_ = Util::Overload {
[](LIB::BasePWMap a) { return ContainerBaseType(a.dom()); },
[](LIB::CanonPWMap a) { return ContainerBaseType(a.dom()); },
[](auto a) {
Util::ERROR("Wrong arguments for dom");
return ContainerBaseType();
}
};
*/

auto combine_visitor_ = Util::Overload {
[](LIB::BasePWMap a, LIB::BasePWMap b) { return MapBaseType(a.combine(b)); },
[](LIB::CanonPWMap a, LIB::CanonPWMap b) {
Expand Down Expand Up @@ -292,15 +246,15 @@ auto connected_visitor_ = Util::Overload {
};

auto matching_visitor_ = Util::Overload {
[](LIB::BaseSBG a, Util::MD_NAT b, bool c) {
LIB::BaseMatch match(a.copy(b[0]), c);
return InfoBaseType(match.calculate());
[](LIB::BaseSBG a, Util::MD_NAT b, Util::MD_NAT c, bool d) {
LIB::BaseMatch match(a.copy(b[0]), d);
return InfoBaseType(match.calculate(c[0]));
},
[](LIB::CanonSBG a, Util::MD_NAT b, bool c) {
LIB::CanonMatch match(a.copy(b[0]), c);
return InfoBaseType(match.calculate());
[](LIB::CanonSBG a, Util::MD_NAT b, Util::MD_NAT c, bool d) {
LIB::CanonMatch match(a.copy(b[0]), d);
return InfoBaseType(match.calculate(c[0]));
},
[](auto a, auto b, auto c) {
[](auto a, auto b, auto c, auto d) {
Util::ERROR("Wrong arguments for matching");
return InfoBaseType();
}
Expand Down Expand Up @@ -336,6 +290,19 @@ auto ts_visitor_ = Util::Overload {
}
};

auto first_inv_visitor_ = Util::Overload {
[](LIB::BasePWMap a) {
return MapBaseType(a.firstInv());
},
[](LIB::CanonPWMap a) {
return MapBaseType(a.firstInv());
},
[](auto a) {
Util::ERROR("Wrong arguments for firstInv");
return MapBaseType();
}
};

// -----------------------------------------------------------------------------
// Expression evaluator --------------------------------------------------------
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -662,13 +629,14 @@ ExprBaseType EvalExpression::operator()(AST::Call v) const
break;

case Eval::Func::matching:
if (eval_args.size() == 2) {
if (eval_args.size() == 3) {
arity_ok = true;

SBGBaseType g = std::visit(EvalGraph{}, eval_args[0]);
NatBaseType copies = std::visit(EvalNatBT{}, eval_args[1]);
NatBaseType k = std::visit(EvalNatBT{}, eval_args[2]);
InfoBaseType result = std::visit(
matching_visitor_, g, copies, std::variant<bool>(debug_)
matching_visitor_, g, copies, k, std::variant<bool>(debug_)
);
return result;
}
Expand Down Expand Up @@ -698,6 +666,15 @@ ExprBaseType EvalExpression::operator()(AST::Call v) const
}
break;

case Eval::Func::first_inv:
if (eval_args.size() == 1) {
arity_ok = true;

MapBaseType pw = std::visit(EvalMap(), eval_args[0]);
MapBaseType result = std::visit(first_inv_visitor_, pw);
return result;
}

default:
Util::ERROR("EvalExpression: function %s not implemented", vname.c_str());
return Util::MD_NAT(0);
Expand Down
4 changes: 2 additions & 2 deletions sbg/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,9 @@ SBGMap<Set> SBGMap<Set>::composition(const SBGMap &other) const
// Extra functions -------------------------------------------------------------

template<typename Set>
SBGMap<Set> SBGMap<Set>::minInv(const Set &d) const
SBGMap<Set> SBGMap<Set>::minInv(const Set &allowed) const
{
Set res_dom = restrict(d).image();
Set res_dom = restrict(allowed).image();

if (dom_.cardinal() == 1 || exp_.isConstant())
return SBGMap<Set>(res_dom, Exp(dom_.minElem()));
Expand Down
2 changes: 1 addition & 1 deletion sbg/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ struct SBGMap {
/**
* @brief Extra operations.
*/
SBGMap minInv(const Set &allowed) const;
SBGMap minInv() const;
SBGMap minInv(const Set &im) const;
bool isId() const;
unsigned int nmbrDims() const;
};
Expand Down
4 changes: 2 additions & 2 deletions sbg/ord_pw_mdinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ OrdPWMDInter OrdPWMDInter::cup(const OrdPWMDInter &other) const
if (pieces_ == other.pieces_)
return pieces_;

if (maxElem() <= other.minElem()) {
if (maxElem() < other.minElem()) {
for (const SetPiece &mdi1 : pieces_)
un.emplaceBack(mdi1);

Expand All @@ -202,7 +202,7 @@ OrdPWMDInter OrdPWMDInter::cup(const OrdPWMDInter &other) const
return OrdPWMDInter(un);
}

if (other.maxElem() <= minElem()) {
if (other.maxElem() < minElem()) {
for (const SetPiece &mdi2 : other.pieces_)
un.emplaceBack(mdi2);

Expand Down
69 changes: 43 additions & 26 deletions sbg/pw_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ PWMap<Set>::PWMap() : maps_() {}
template<typename Set>
PWMap<Set>::PWMap(Set s) : maps_() {
if (!s.isEmpty()) {
SBGMap<Set> sbgmap(s, Exp(s.begin()->size(), LExp()));
maps_.emplace(sbgmap);
SBGMap<Set> map(s, Exp(s.begin()->size(), LExp()));
maps_.push_back(map);
}
}
template<typename Set>
PWMap<Set>::PWMap(Map map) : maps_() {
if (!map.dom().isEmpty())
maps_.emplace(map);
maps_.push_back(map);
}
template<typename Set>
PWMap<Set>::PWMap(MS maps) : maps_(maps) {}
Expand Down Expand Up @@ -89,13 +89,13 @@ std::size_t PWMap<Set>::size() const { return maps_.size(); }
template<typename Set>
void PWMap<Set>::emplace(Map map) {
if (!map.dom().isEmpty())
maps_.emplace_hint(maps_.end(), map);
maps_.push_back(map);
}
template<typename Set>
void PWMap<Set>::emplaceBack(Map map)
{
if (!map.dom().isEmpty())
maps_.emplace_hint(maps_.end(), map);
maps_.push_back(map);
}

template<typename Set>
Expand Down Expand Up @@ -223,6 +223,30 @@ Set PWMap<Set>::preImage(const Set &subcodom) const
return res;
}

template<typename Set>
PWMap<Set> PWMap<Set>::inverse() const
{
PWMap res;

for (const Map &map : maps_) {
if (!map.exp().isConstant()) {
Set new_dom = map.image();
Exp new_exp = map.exp().inverse();
res.emplaceBack(Map(new_dom, new_exp));
}
else if (map.dom().cardinal() == 1) {
Set new_dom = map.image();
Exp new_exp(map.dom().minElem());
res.emplaceBack(Map(new_dom, new_exp));
}
else {
Util::ERROR("LIB::PWMap::inverse: map is not bijective");
}
}

return res;
}

template<typename Set>
PWMap<Set> PWMap<Set>::composition(const PWMap &other) const
{
Expand Down Expand Up @@ -285,16 +309,16 @@ PWMap<Set> PWMap<Set>::concatenation(const PWMap &other) const
template<typename Set>
PWMap<Set> PWMap<Set>::combine(const PWMap &other) const
{
PWMap res = *this;

if (isEmpty())
return other;

if (other.isEmpty())
return *this;

PWMap res = *this;
Set dom1 = dom();
for (const Map &map2 : other.maps_) {
Set dom2 = map2.dom(), new_dom = dom2.difference(dom());
Set dom2 = map2.dom(), new_dom = dom2.difference(dom1);
res.emplaceBack(Map(new_dom, map2.exp()));
}

Expand Down Expand Up @@ -721,33 +745,26 @@ PWMap<Set> PWMap<Set>::minAdjMap(const PWMap &other) const
}

template<typename Set>
PWMap<Set> PWMap<Set>::minInv(const Set &d) const
PWMap<Set> PWMap<Set>::firstInv(const Set &allowed) const
{
PWMap res;

if (!isEmpty() && !d.isEmpty()) {
Map first = *begin();
res.emplaceBack(first.minInv(d));
for (const Map &map : maps_) {
Map ith = map.minInv(d);
Set cap_dom = ith.dom().intersection(res.dom());
Set visited;
for (const Map &map : maps_) {
Set res_dom = map.image(allowed).difference(visited);
if (!res_dom.isEmpty()) {
Map new_map(map.preImage(res_dom), map.exp());
res.emplaceBack(new_map.minInv());

if (!cap_dom.isEmpty()) {
PWMap min = res.minMap(PWMap(ith));
res = min.combine(res);
Set diff = ith.dom().difference(res.dom());
res.emplaceBack(Map(diff, ith.exp()));
}
else
res.emplaceBack(ith);
visited = visited.cup(map.image(allowed));
}
}

return res;
}

template<typename Set>
PWMap<Set> PWMap<Set>::minInv() const { return minInv(dom()); }
PWMap<Set> PWMap<Set>::firstInv() const { return firstInv(dom()); }

template<typename Set>
PWMap<Set> PWMap<Set>::filterMap(bool (*f)(const SBGMap<Set> &)) const
Expand Down Expand Up @@ -847,9 +864,9 @@ PWMap<Set> PWMap<Set>::normalize(const PWMap &other) const
{
PWMap res;

Set visited;
Set visited, dom1;
for (const Map &map1 : maps_) {
Set ith = dom();
Set ith = dom1;
if (ith.intersection(visited).isEmpty()) {
for (const Map &map2 : maps_)
if (map1.exp() == map2.exp())
Expand Down
27 changes: 21 additions & 6 deletions sbg/pw_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
#ifndef SBG_PWMAP_HPP
#define SBG_PWMAP_HPP

#include <boost/container/flat_set.hpp>

#include "sbg/map.hpp"

namespace SBG {
Expand All @@ -37,7 +35,7 @@ namespace LIB {
*/

template<typename Set>
using MapSet = boost::unordered::unordered_flat_set<SBGMap<Set>>;
using MapSet = std::vector<SBGMap<Set>>;
template<typename Set>
std::ostream &operator<<(std::ostream &out, const MapSet<Set> &ms);

Expand Down Expand Up @@ -79,6 +77,12 @@ struct PWMap {
Set image(const Set &subdom) const;
Set preImage() const;
Set preImage(const Set &subcodom) const;
/** @function inverse
*
* @brief Calculate the inverse of a bijective pw_map. Throws error if it is
* not bijective.
*/
PWMap inverse() const;
/** @function composition
*
* @brief Apply first pw2, then pw1 (i.e. pw1(pw2(x)) is calculated).
Expand Down Expand Up @@ -141,12 +145,23 @@ struct PWMap {
PWMap minAdjMap(const PWMap &other1, const PWMap &other2) const;
PWMap minAdjMap(const PWMap &other) const;

PWMap minInv(const Set &im) const;
PWMap minInv() const;
/** @function firstInv
*
* @brief Calculate the inverse of a pw_map. If it is not injective,
* for the elements with more than one preImage, it will assign the first
* appearing inverted expression that maps to that element.
*
* @param allowed
*/
PWMap firstInv(const Set &allowed) const;
PWMap firstInv() const;

PWMap filterMap(bool (*f)(const SBGMap<Set> &)) const;

// Returns elements in both doms, that have the same image in both maps
/** @function equalImage
*
* @brief Return elements in both doms, that have the same image in both maps
*/
Set equalImage(const PWMap &other) const;

PWMap offsetDom(const Util::MD_NAT &off) const;
Expand Down
Loading

0 comments on commit c7b4c65

Please sign in to comment.