Skip to content

Commit 6d74fef

Browse files
committed
Shortest path per function search heuristic
Computes the shortest path per function on the shortest path graph and uses this heuristic to guide the symex search
1 parent 636c366 commit 6d74fef

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

src/symex/path_search.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,42 @@ void path_searcht::sort_queue()
6565
}
6666
}
6767

68+
// We prioritise remaining in the same function, but if there is no choice
69+
// we take the next state with the shortest path
70+
void path_searcht::sort_queue_per_function()
71+
{
72+
debug()<< " get shortest path, queue.size = " <<queue.size() <<eom;
73+
if(queue.size()==1)
74+
{
75+
current_distance = queue.front().get_shortest_path();
76+
return;
77+
}
78+
79+
unsigned shortest_path = std::numeric_limits<unsigned>::max();
80+
81+
std::list<statet>::iterator it;
82+
std::list<statet>::iterator closest_state;
83+
84+
// pick the first state in the queue that is a direct successor, i.e.,
85+
// has a path length 1 less than the current path length
86+
for(it=queue.begin(); it!=queue.end(); ++it)
87+
{
88+
if(it->get_shortest_path()+1 == current_distance)
89+
{
90+
shortest_path = it->get_shortest_path();
91+
current_distance = shortest_path;
92+
statet tmp = *it;
93+
queue.erase(it);
94+
queue.push_front(tmp);
95+
return;
96+
}
97+
}
98+
99+
// if we get here there was no direct successor, we revert to
100+
// picking the shortest path
101+
sort_queue();
102+
}
103+
68104
void path_searcht::shuffle_queue(queuet &queue)
69105
{
70106
if(queue.size()<=1)
@@ -120,6 +156,12 @@ path_searcht::resultt path_searcht::operator()(
120156
status()<<"Building shortest path graph" << eom;
121157
shortest_path_grapht shortest_path_graph(goto_functions, locs);
122158
}
159+
else if(search_heuristic == search_heuristict::SHORTEST_PATH_PER_FUNC)
160+
{
161+
status()<<"Building shortest path graph per function" << eom;
162+
per_function_shortest_patht shortest_path_graph(goto_functions, locs);
163+
}
164+
123165
statet init_state = initial_state(var_map, locs, history);
124166
queue.push_back(init_state);
125167
initial_distance_to_property=init_state.get_shortest_path();
@@ -308,6 +350,9 @@ void path_searcht::pick_state()
308350
case search_heuristict::SHORTEST_PATH:
309351
sort_queue();
310352
return;
353+
case search_heuristict::SHORTEST_PATH_PER_FUNC:
354+
sort_queue_per_function();
355+
return;
311356
case search_heuristict::LOCS:
312357
return;
313358
}

src/symex/path_search.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ class path_searcht:public safety_checkert
116116
{ search_heuristic=search_heuristict::SHORTEST_PATH; }
117117
void set_ran_shortest_path()
118118
{ search_heuristic=search_heuristict::RAN_SHORTEST_PATH; }
119+
void set_shortest_path_per_function()
120+
{ search_heuristic=search_heuristict::SHORTEST_PATH_PER_FUNC; }
119121

120122
typedef std::map<irep_idt, property_entryt> property_mapt;
121123
property_mapt property_map;
@@ -133,6 +135,7 @@ class path_searcht:public safety_checkert
133135
/// Move element with shortest distance to property
134136
/// to the front of the queue
135137
void sort_queue();
138+
void sort_queue_per_function();
136139
// search heuristic
137140
void pick_state();
138141

@@ -164,7 +167,8 @@ class path_searcht:public safety_checkert
164167
unsigned time_limit;
165168

166169
enum class search_heuristict
167-
{ DFS, RAN_DFS, BFS, LOCS, SHORTEST_PATH, RAN_SHORTEST_PATH } search_heuristic;
170+
{ DFS, RAN_DFS, BFS, LOCS, SHORTEST_PATH,
171+
RAN_SHORTEST_PATH , SHORTEST_PATH_PER_FUNC } search_heuristic;
168172

169173
source_locationt last_source_location;
170174
};

src/symex/symex_parse_options.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ int symex_parse_optionst::doit()
243243
else
244244
path_search.set_shortest_path();
245245
}
246+
247+
if(cmdline.isset("shortest-path-per-function"))
248+
path_search.set_shortest_path_per_function();
249+
246250
if(cmdline.isset("show-vcc"))
247251
{
248252
path_search.show_vcc=true;
@@ -653,6 +657,7 @@ void symex_parse_optionst::help()
653657
" --dfs use depth first search\n"
654658
" --bfs use breadth first search\n"
655659
"--shortest-path use shortest path guided search\n"
660+
"--shortest-path-per-function computes shortest path locally and uses to guide symex search\n" // NOLINT(*)
656661
" --randomize in conjunction with dfs to use randomized dfs\n" // NOLINT(*)
657662
" in conjunction with shortest path to use randomized shortest path guided search\n" // NOLINT(*)
658663
" --eager-infeasibility query solver early to determine whether a path is infeasible before searching it\n" // NOLINT(*)

src/symex/symex_parse_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class optionst;
3939
"(error-label):(verbosity):(no-library)" \
4040
"(version)" \
4141
"(bfs)(dfs)(locs)(shortest-path)" \
42+
"(shortest-path-per-function)" \
4243
"(randomize)" \
4344
"(cover):" \
4445
"(i386-linux)(i386-macos)(i386-win32)(win32)(winx64)(gcc)" \

0 commit comments

Comments
 (0)