File: iesolver.cc

package info (click to toggle)
gringo 5.8.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 32,128 kB
  • sloc: cpp: 210,867; ansic: 37,507; python: 11,271; yacc: 825; javascript: 627; sh: 368; xml: 364; makefile: 102
file content (90 lines) | stat: -rw-r--r-- 3,673 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include "gringo/term.hh"
#include "tests/tests.hh"

namespace Gringo {
namespace Input {
namespace Test {

struct DummyContext : IEContext {
    void gatherIEs(IESolver &solver) const override { static_cast<void>(solver); }
    void addIEBound(VarTerm const &var, IEBound const &bound) override { bounds.emplace(&var, bound); }
    IEBoundMap bounds;
};

TEST_CASE("iesolver", "[iesolver]") {
    SECTION("base") {
        auto valX = std::make_shared<Symbol>(Symbol::createNum(0));
        auto valY = std::make_shared<Symbol>(Symbol::createNum(0));
        Location loc{"", 0, 0, "", 0, 0};
        auto X = make_locatable<VarTerm>(loc, "X", valX);
        auto Y = make_locatable<VarTerm>(loc, "Y", valY);
        DummyContext ctx;
        IESolver slv{ctx};
        slv.add({{{1, X.get()}}, 2}, false);
        slv.add({{{1, Y.get()}, {-1, X.get()}}, 1}, false);
        slv.add({{{-1, X.get()}, {-1, Y.get()}}, -100}, false);

        slv.compute();
        auto const bounds = std::move(ctx.bounds);
        auto itX = bounds.find(X.get());
        auto itY = bounds.find(Y.get());
        REQUIRE(!bounds.empty());
        REQUIRE(itX != bounds.end());
        REQUIRE(itY != bounds.end());
        REQUIRE(itX->second.isSet(IEBound::Lower));
        REQUIRE(itX->second.isSet(IEBound::Upper));
        REQUIRE(itY->second.isSet(IEBound::Lower));
        REQUIRE(itY->second.isSet(IEBound::Upper));
        REQUIRE(itX->second.get(IEBound::Lower) == 2);
        REQUIRE(itX->second.get(IEBound::Upper) == 97);
        REQUIRE(itY->second.get(IEBound::Lower) == 3);
        REQUIRE(itY->second.get(IEBound::Upper) == 98);
    }
    SECTION("bug") {
        // X=1..2, Y=0, Z=X+3*Y.
        auto valX = std::make_shared<Symbol>(Symbol::createNum(0));
        auto valY = std::make_shared<Symbol>(Symbol::createNum(0));
        auto valZ = std::make_shared<Symbol>(Symbol::createNum(0));
        Location loc{"", 0, 0, "", 0, 0};
        auto X = make_locatable<VarTerm>(loc, "X", valX);
        auto Y = make_locatable<VarTerm>(loc, "Y", valY);
        auto Z = make_locatable<VarTerm>(loc, "Z", valZ);
        DummyContext ctx;
        IESolver slv{ctx};
        // X=1..2
        slv.add({{{1, X.get()}}, 1}, false);   // X>=1
        slv.add({{{-1, X.get()}}, -2}, false); // X<=2
        // Y=0
        slv.add({{{1, Y.get()}}, 0}, false);  // Y>=0
        slv.add({{{-1, Y.get()}}, 0}, false); // Y<=0
        // Z-X-3*Y=0
        slv.add({{{1, Z.get()}, {-1, X.get()}, {-3, Y.get()}}, 0}, false); // Z-X-3*Y>=0
        slv.add({{{-1, Z.get()}, {1, X.get()}, {3, Y.get()}}, 0}, false);  // -Z+X+3*Y<=0

        slv.compute();
        auto const bounds = std::move(ctx.bounds);
        auto itX = bounds.find(X.get());
        auto itY = bounds.find(Y.get());
        auto itZ = bounds.find(Z.get());
        REQUIRE(!bounds.empty());
        REQUIRE(itX != bounds.end());
        REQUIRE(itY != bounds.end());
        REQUIRE(itZ != bounds.end());
        REQUIRE(itX->second.isSet(IEBound::Lower));
        REQUIRE(itX->second.isSet(IEBound::Upper));
        REQUIRE(itY->second.isSet(IEBound::Lower));
        REQUIRE(itY->second.isSet(IEBound::Upper));
        REQUIRE(itZ->second.isSet(IEBound::Lower));
        REQUIRE(itZ->second.isSet(IEBound::Upper));
        REQUIRE(itX->second.get(IEBound::Lower) == 1);
        REQUIRE(itX->second.get(IEBound::Upper) == 2);
        REQUIRE(itY->second.get(IEBound::Lower) == 0);
        REQUIRE(itY->second.get(IEBound::Upper) == 0);
        REQUIRE(itZ->second.get(IEBound::Lower) == 1);
        REQUIRE(itZ->second.get(IEBound::Upper) == 2);
    }
}

} // namespace Test
} // namespace Input
} // namespace Gringo