+ud option of mealy_machine_to_aig received wrong value

Also aiger received a tracing option for
debugging

* spot/twaalgos/aiger.cc: Here
* tests/core/ltlsynt.test: Test
This commit is contained in:
Philipp Schlehuber-Caissier 2022-04-06 21:16:35 +02:00
parent 524edea8da
commit 06b73c39fa
2 changed files with 164 additions and 44 deletions

View file

@ -30,6 +30,7 @@
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <initializer_list>
#include <spot/twa/twagraph.hh> #include <spot/twa/twagraph.hh>
#include <spot/misc/bddlt.hh> #include <spot/misc/bddlt.hh>
@ -41,6 +42,13 @@
#define STR_(x) STR(x) #define STR_(x) STR(x)
#define STR_LINE STR_(__LINE__) #define STR_LINE STR_(__LINE__)
//#define TRACE
#ifdef TRACE
# define trace std::cerr
#else
# define trace while (0) std::cerr
#endif
namespace namespace
{ {
using namespace spot; using namespace spot;
@ -459,6 +467,7 @@ namespace spot
aig::roll_back_(safe_point sf, bool do_stash) aig::roll_back_(safe_point sf, bool do_stash)
{ {
// todo specialise for safe_all? // todo specialise for safe_all?
trace << "Roll back to sf: " << sf.first << "; " << sf.second << '\n';
safe_stash ss; safe_stash ss;
auto& [gates, vardict, negs] = ss; auto& [gates, vardict, negs] = ss;
if (do_stash) if (do_stash)
@ -480,6 +489,7 @@ namespace spot
// Copy the gates // Copy the gates
std::copy(and_gates_.begin()+sf.second, and_gates_.end(), std::copy(and_gates_.begin()+sf.second, and_gates_.end(),
gates.begin()); gates.begin());
trace << "Safed " << gates.size() << '\n';
} }
// 1. Delete all literals // 1. Delete all literals
// max_var_old was used before // max_var_old was used before
@ -489,6 +499,8 @@ namespace spot
// 2. Set back the gates // 2. Set back the gates
and_gates_.erase(and_gates_.begin() + sf.second, and_gates_.end()); and_gates_.erase(and_gates_.begin() + sf.second, and_gates_.end());
max_var_ = sf.first; max_var_ = sf.first;
trace << "After rollback: \n" << and_gates_.size() << " gates and\n"
<< max_var_ << " variables\n\n";
return ss; return ss;
} }
@ -497,6 +509,8 @@ namespace spot
{ {
// Do some check_ups // Do some check_ups
auto& [gates, vardict, _] = ss; auto& [gates, vardict, _] = ss;
trace << "Reapplying sf: " << sf.first << "; " << sf.second
<< "\nwith " << gates.size() << " additional gates.\n\n";
assert(gates.size() == vardict.size()); assert(gates.size() == vardict.size());
assert(sf.first == max_var_); assert(sf.first == max_var_);
assert(sf.second == and_gates_.size()); assert(sf.second == and_gates_.size());
@ -511,6 +525,7 @@ namespace spot
and_gates_.insert(and_gates_.end(), and_gates_.insert(and_gates_.end(),
gates.begin(), gates.end()); gates.begin(), gates.end());
max_var_ = new_max_var_; max_var_ = new_max_var_;
trace << "New Ngates: " << num_gates() << '\n';
} }
void aig::set_output(unsigned i, unsigned v) void aig::set_output(unsigned i, unsigned v)
@ -698,7 +713,6 @@ namespace spot
while ((prod = cond.next()) != bddfalse) while ((prod = cond.next()) != bddfalse)
plus_vars_.push_back(cube2var_(prod, plus_vars_.push_back(cube2var_(prod,
use_split_off == 2 ? 0 : use_split_off)); use_split_off == 2 ? 0 : use_split_off));
// Done building -> sum them // Done building -> sum them
return aig_or(plus_vars_); return aig_or(plus_vars_);
} }
@ -709,12 +723,21 @@ namespace spot
{ {
// Before doing anything else, let us check if one the variables // Before doing anything else, let us check if one the variables
// already exists in which case we are done // already exists in which case we are done
#ifdef TRACE
trace << "encoding one of \n";
for (const auto& c: c_alt)
trace << c << '\n';
#endif
for (const bdd& cond : c_alt) for (const bdd& cond : c_alt)
{ {
auto it = bdd2var_.find(cond.id()); auto it = bdd2var_.find(cond.id());
if (it != bdd2var_.end()) if (it != bdd2var_.end())
{
trace << "Condition already encoded -> Direct return\n\n";
return it->second; return it->second;
} }
}
safe_point sf = get_safe_point_(); safe_point sf = get_safe_point_();
@ -732,9 +755,6 @@ namespace spot
&& "Cannot convert the given method. " && "Cannot convert the given method. "
"Only 0,1 and 2 are currently supported"); "Only 0,1 and 2 are currently supported");
const auto negate = use_dual ? std::vector<bool>{false}
: std::vector<bool>{false, true};
auto enc_1 = [&](const bdd& b, auto enc_1 = [&](const bdd& b,
const char m) const char m)
{ {
@ -751,7 +771,11 @@ namespace spot
std::vector<bdd> cond_parts; std::vector<bdd> cond_parts;
std::vector<unsigned> cond_vars; std::vector<unsigned> cond_vars;
for (bool do_negate : negate) //for (bool do_negate : (use_dual ? std::initializer_list<bool>{false, true}
// : std::initializer_list<bool>{false}))
for (unsigned neg_counter = 0; neg_counter <= 0 + use_dual; ++neg_counter)
{
bool do_negate = neg_counter;
for (const bdd& b : c_alt) for (const bdd& b : c_alt)
{ {
bdd b_used = do_negate ? bdd_not(b) : b; bdd b_used = do_negate ? bdd_not(b) : b;
@ -769,23 +793,38 @@ namespace spot
break; // Cannot be optimal break; // Cannot be optimal
} }
// Compute the and if there is still hope // Compute the and if there is still hope
unsigned this_res = -1u; auto this_res = -1u;
if (num_gates() < ngates_min) if (num_gates() < ngates_min)
this_res = aig_and(cond_vars); this_res = aig_and(cond_vars);
// Check if after adding these gates
// the circuit is still smaller
if (num_gates() < ngates_min) if (num_gates() < ngates_min)
{ {
// This is the new best // This is the new best
assert(this_res != -1u);
res_var = do_negate ? aig_not(this_res) : this_res; res_var = do_negate ? aig_not(this_res) : this_res;
ngates_min = num_gates(); ngates_min = num_gates();
trace << "Found new best encoding with\nneg: "
<< do_negate << "\nmethod: " << (m == 0 ? "INF"
: "ISOP")
<< "\nalt: " << b
<< "\nNgates: " << num_gates() << "\n\n";
ss_min = roll_back_(sf, true); ss_min = roll_back_(sf, true);
} }
else else
// Reset the computations // Reset the computations
{
trace << "Method \nneg: "
<< do_negate << "\nmethod: " << (m == 0 ? "INF"
: "ISOP")
<< "\nalt: " << b
<< "\nNgates: " << num_gates()
<< " discarded.\n\n";
roll_back_(sf, false); roll_back_(sf, false);
}
} // Encoding styles } // Encoding styles
} // alternatives } // alternatives
// end do_negate } // end do_negate
// Reapply the best result // Reapply the best result
reapply_(sf, ss_min); reapply_(sf, ss_min);
@ -1753,6 +1792,7 @@ namespace
bool use_dual = false; bool use_dual = false;
bool use_dontcare = false; bool use_dontcare = false;
int use_split_off = 0; int use_split_off = 0;
std::string s;
}; };
auto to_treat = [&mode]() auto to_treat = [&mode]()
@ -1766,6 +1806,8 @@ namespace
while (std::getline(s, buffer, ',')) while (std::getline(s, buffer, ','))
{ {
tr_opt this_opt; tr_opt this_opt;
// Store raw info
this_opt.s = buffer;
std::stringstream s2; std::stringstream s2;
s2 << buffer; s2 << buffer;
std::getline(s2, buffer2, '+'); std::getline(s2, buffer2, '+');
@ -1865,15 +1907,16 @@ namespace
}; };
// Create the vars // Create the vars
std::vector<bdd> alt_conds(amodedescr.use_dontcare ? 1 : 2);
for (unsigned i = 0; i < n_outs; ++i) for (unsigned i = 0; i < n_outs; ++i)
{ {
trace << "Assign out " << i << '\n';
if (circuit.num_gates() > min_gates) if (circuit.num_gates() > min_gates)
break; break;
circuit.set_output(i, bdd2var(out[i], out_dc[i])); circuit.set_output(i, bdd2var(out[i], out_dc[i]));
} }
for (unsigned i = 0; i < n_latches; ++i) for (unsigned i = 0; i < n_latches; ++i)
{ {
trace << "Assign latch " << i << '\n';
if (circuit.num_gates() > min_gates) if (circuit.num_gates() > min_gates)
break; break;
circuit.set_next_latch(i, bdd2var(latch[i], bddfalse)); circuit.set_next_latch(i, bdd2var(latch[i], bddfalse));
@ -1883,6 +1926,8 @@ namespace
// Overwrite the stash if we generated less gates // Overwrite the stash if we generated less gates
if (circuit.num_gates() < min_gates) if (circuit.num_gates() < min_gates)
{ {
trace << "New best mode: " << amodedescr.s
<< " with Ngates: " << circuit.num_gates() << '\n';
min_gates = circuit.num_gates(); min_gates = circuit.num_gates();
ss = circuit.roll_back_(sf, true); ss = circuit.roll_back_(sf, true);
bdd2var_min = bdd2var; bdd2var_min = bdd2var;
@ -1892,6 +1937,8 @@ namespace
} }
//Use the best sol //Use the best sol
circuit.reapply_(sf, ss); circuit.reapply_(sf, ss);
trace << "Finished encoding, reasssigning\n"
<< "Final gate count is " << circuit.num_gates() << '\n';
// Reset them // Reset them
for (unsigned i = 0; i < n_outs; ++i) for (unsigned i = 0; i < n_outs; ++i)
circuit.set_output(i, bdd2var_min(out[i], out_dc[i])); circuit.set_output(i, bdd2var_min(out[i], out_dc[i]));

View file

@ -470,10 +470,81 @@ i3 i3
o0 o0 o0 o0
o1 o1 o1 o1
EOF EOF
ltlsynt -f "G((i0 && i1)<->X(o0)) && G((i2|i3)<->X(o1))" --outs="o0,o1"\
--aiger=isop+ud --algo=lar --decompose=no --simpl=no >out
diff out exp
cat >exp <<EOF
REALIZABLE
aag 54 4 3 2 47
2
4
6
8
10 39
12 87
14 109
25
31
16 11 13
18 14 16
20 10 12
22 15 20
24 19 23
26 11 12
28 15 26
30 19 29
32 7 9
34 16 32
36 15 32
38 35 37
40 3 6
42 16 40
44 15 40
46 3 8
48 16 46
50 15 46
52 2 4
54 34 52
56 36 52
58 5 6
60 16 58
62 15 58
64 5 8
66 16 64
68 15 64
70 43 45
72 49 51
74 55 57
76 61 63
78 67 69
80 70 72
82 74 76
84 78 80
86 82 84
88 6 16
90 52 88
92 6 15
94 52 92
96 8 16
98 52 96
100 8 15
102 52 100
104 91 95
106 99 103
108 104 106
i0 i0
i1 i1
i2 i2
i3 i3
o0 o0
o1 o1
EOF
ltlsynt -f "G((i0 && i1)<->X(o0)) && G((i2|i3)<->X(o1))" --outs="o0,o1"\ ltlsynt -f "G((i0 && i1)<->X(o0)) && G((i2|i3)<->X(o1))" --outs="o0,o1"\
--aiger=isop --algo=lar --decompose=no --simpl=no >out --aiger=isop --algo=lar --decompose=no --simpl=no >out
diff out exp diff out exp
cat >exp <<EOF cat >exp <<EOF
REALIZABLE REALIZABLE
aag 18 4 4 2 10 aag 18 4 4 2 10
@ -505,10 +576,10 @@ o0 o0
o1 o1 o1 o1
EOF EOF
ltlsynt -f "G((i0 && i1)<->X(o0)) && G((i2|i3)<->X(o1))" --outs="o0,o1"\ ltlsynt -f "G((i0 && i1)<->X(o0)) && G((i2|i3)<->X(o1))" --outs="o0,o1"\
--aiger=isop --algo=lar --decompose=yes --simpl=no >out --aiger=isop+ud --algo=lar --decompose=yes --simpl=no >out
diff out exp diff out exp
ltlsynt -f "G((i0 && i1)<->X(o0)) && G((i2|i3)<->X(o1))" --outs="o0,o1"\ ltlsynt -f "G((i0 && i1)<->X(o0)) && G((i2|i3)<->X(o1))" --outs="o0,o1"\
--aiger=isop --algo=lar --simpl=no >out --aiger=isop+ud --algo=lar --simpl=no >out
diff out exp diff out exp
# Issue #477 # Issue #477
@ -794,8 +865,10 @@ LTL='(((((G (((((((g_0) && (G (! (r_0)))) -> (F (! (g_0)))) && (((g_0) &&
&& ((r_0) R (! (g_0)))) && (G ((r_0) -> (F (g_0))))) && ((r_1) R (! (g_1)))) && && ((r_0) R (! (g_0)))) && (G ((r_0) -> (F (g_0))))) && ((r_1) R (! (g_1)))) &&
(G ((r_1) -> (F (g_1)))))' (G ((r_1) -> (F (g_1)))))'
OUT='g_0, g_1' OUT='g_0, g_1'
ltlsynt --outs="$OUT" -f "$LTL" --aiger=both --algo=acd | grep "aag 8 2 2 2 4" ltlsynt --outs="$OUT" -f "$LTL" --aiger=both+ud\
ltlsynt --outs="$OUT" -f "$LTL" --aiger=both --algo=lar | grep "aag 34 2 3 2 29" --algo=acd | grep "aag 8 2 2 2 4"
ltlsynt --outs="$OUT" -f "$LTL" --aiger=both+ud\
--algo=lar | grep "aag 34 2 3 2 29"
ltlsynt -f 'G(c) & (G(a) <-> GFb)' --outs=b,c --decompose=yes\ ltlsynt -f 'G(c) & (G(a) <-> GFb)' --outs=b,c --decompose=yes\
--verbose --realizability 2> out --verbose --realizability 2> out