Skip to content

Commit ce957e6

Browse files
committed
Parse HOA AP header
The numbering that Spot uses for the atoms in the given formula need not match ours; hence, this adds parsing for the "AP:" header in Spot's HOA output.
1 parent d4de8c0 commit ce957e6

File tree

7 files changed

+53
-13
lines changed

7 files changed

+53
-13
lines changed

regression/ebmc-spot/sva-buechi/if1.k.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
CORE
22
../../verilog/SVA/if1.sv
3-
--buechi --k-induction --bound 1
3+
--buechi --k-induction --bound 2
44
^\[main\.p0\] always \(if\(main\.counter == 0\) nexttime main\.counter == 1\): PROVED$
55
^\[main\.p1\] always \(if\(main\.counter == 0\) nexttime main\.counter == 1 else nexttime main\.counter == 3\): REFUTED$
66
^EXIT=10$
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
../../verilog/SVA/s_eventually2.sv
33
--buechi --module main --bound 20
44
^\[main\.p0\] always s_eventually main.reset \|\| main\.counter == 10: PROVED up to bound 20$
@@ -8,4 +8,3 @@ KNOWNBUG
88
--
99
^warning: ignoring
1010
--
11-
This gives the wrong answer for main.p0.

src/temporal-logic/hoa.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,28 @@ hoat::headert hoa_parsert::parse_header()
266266
return header;
267267
}
268268

269+
hoat::ap_mapt hoat::parse_AP() const
270+
{
271+
for(auto &item : header)
272+
{
273+
if(item.first == "AP:")
274+
{
275+
hoat::ap_mapt result;
276+
std::size_t index = 0;
277+
for(auto &name : item.second)
278+
{
279+
if(index != 0)
280+
result[index - 1] = name;
281+
index++;
282+
}
283+
return result;
284+
}
285+
}
286+
287+
// header not found
288+
return {};
289+
}
290+
269291
hoat::bodyt hoa_parsert::parse_body()
270292
{
271293
if(!tokenizer.consume().is_body())
@@ -323,8 +345,6 @@ hoat::edgest hoa_parsert::parse_edges()
323345
return edges;
324346
}
325347

326-
#include <iostream>
327-
328348
hoat::edget hoa_parsert::parse_edge()
329349
{
330350
edget edge;

src/temporal-logic/hoa.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ class hoat
6868
intt max_state_number() const;
6969

7070
// atomic propositions
71-
std::map<intt, std::string> ap_map;
71+
using ap_mapt = std::map<intt, std::string>;
72+
73+
// parses the AP header
74+
ap_mapt parse_AP() const;
7275

7376
// convert into a graph
7477
struct graph_edget

src/temporal-logic/ltl_sva_to_string.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, dkr@amazon.com
1111
#include <util/arith_tools.h>
1212
#include <util/string2int.h>
1313

14+
#include <ebmc/ebmc_error.h>
1415
#include <verilog/sva_expr.h>
1516

1617
#include "ltl.h"
@@ -21,8 +22,11 @@ Author: Daniel Kroening, dkr@amazon.com
2122

2223
exprt ltl_sva_to_stringt::atom(const std::string &string) const
2324
{
25+
if(string.empty() || string[0] != 'a')
26+
throw ebmc_errort{} << "got unexpected atom '" << string << "'";
27+
2428
// map back to number
25-
auto number = safe_string2size_t(string);
29+
auto number = safe_string2size_t(string.substr(1, std::string::npos));
2630

2731
PRECONDITION(number < atoms.size());
2832

src/temporal-logic/ltl_sva_to_string.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class ltl_sva_to_stringt
5353
std::string s;
5454
};
5555

56+
// This maps our expressions to a number.
57+
// Spot may or may not use the same numbering in the AP header.
5658
numberingt<exprt, irep_hash> atoms;
5759

5860
using modet = enum { PROPERTY, SVA_SEQUENCE, BOOLEAN };

src/temporal-logic/ltl_to_buechi.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, dkr@amazon.com
1616
#include <util/run.h>
1717
#include <util/std_expr.h>
1818
#include <util/std_types.h>
19+
#include <util/string2int.h>
1920

2021
#include <ebmc/ebmc_error.h>
2122
#include <trans-word-level/next_symbol.h>
@@ -46,12 +47,13 @@ void buechi_transt::rename_state_symbol(const symbol_exprt &new_state_symbol)
4647

4748
exprt hoa_label_to_expr(
4849
const hoat::labelt &label,
49-
const ltl_sva_to_stringt &ltl_sva_to_string)
50+
const ltl_sva_to_stringt &ltl_sva_to_string,
51+
const hoat::ap_mapt &ap_map)
5052
{
5153
std::vector<exprt> operands;
5254
operands.reserve(label.get_sub().size());
5355
for(auto &sub : label.get_sub())
54-
operands.push_back(hoa_label_to_expr(sub, ltl_sva_to_string));
56+
operands.push_back(hoa_label_to_expr(sub, ltl_sva_to_string, ap_map));
5557

5658
if(label.id() == "t")
5759
{
@@ -78,8 +80,17 @@ exprt hoa_label_to_expr(
7880
}
7981
else
8082
{
81-
// atomic proposition, given as number
82-
return ltl_sva_to_string.atom(label.id_string());
83+
// Atomic proposition, given as number. This is the numbering
84+
// from the "AP" header, which then maps to a string "aX", which
85+
// is our atom number. These may or may not match.
86+
auto spot_ap_number = safe_string2size_t(label.id_string());
87+
88+
auto ap_map_it = ap_map.find(spot_ap_number);
89+
if(ap_map_it == ap_map.end())
90+
throw ebmc_errort{} << "failed to find atom " << label.id()
91+
<< " in AP header";
92+
93+
return ltl_sva_to_string.atom(ap_map_it->second);
8394
}
8495
}
8596

@@ -150,6 +161,7 @@ ltl_to_buechi(const exprt &property, message_handlert &message_handler)
150161
hoa.buechi_acceptance_cleanup();
151162

152163
auto max_state_number = hoa.max_state_number();
164+
auto ap_map = hoa.parse_AP();
153165
auto state_type = range_typet{0, max_state_number};
154166
const auto buechi_state = symbol_exprt{"buechi::state", state_type};
155167
const auto buechi_next_state =
@@ -220,7 +232,7 @@ ltl_to_buechi(const exprt &property, message_handlert &message_handler)
220232
{
221233
auto pre = equal_exprt{
222234
buechi_state, from_integer(state.first.number, state_type)};
223-
auto cond = hoa_label_to_expr(edge.label, ltl_sva_to_string);
235+
auto cond = hoa_label_to_expr(edge.label, ltl_sva_to_string, ap_map);
224236
error_disjuncts.push_back(and_exprt{pre, cond});
225237
}
226238
}
@@ -242,7 +254,7 @@ ltl_to_buechi(const exprt &property, message_handlert &message_handler)
242254
{
243255
if(edge.dest_states.size() != 1)
244256
throw ebmc_errort() << "edge must have one destination state";
245-
auto cond = hoa_label_to_expr(edge.label, ltl_sva_to_string);
257+
auto cond = hoa_label_to_expr(edge.label, ltl_sva_to_string, ap_map);
246258
auto post = equal_exprt{
247259
buechi_next_state,
248260
from_integer(edge.dest_states.front(), state_type)};

0 commit comments

Comments
 (0)