Skip to content

Commit 426127f

Browse files
committed
SAT-based neural ranking engine
This adds a variant of neural ranking that uses a SAT solver to compute the weights and biases in the neural network.
1 parent 9f4a9dc commit 426127f

13 files changed

+939
-1
lines changed

examples/Benchmarks/run_solver_nuterm

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#!/bin/sh
2+
3+
set -e
4+
5+
if false ; then
6+
# ok
7+
ebmc PWM_1.sv --solver-neural-liveness
8+
ebmc PWM_2.sv --solver-neural-liveness
9+
ebmc PWM_3.sv --solver-neural-liveness
10+
ebmc PWM_4.sv --solver-neural-liveness
11+
ebmc PWM_5.sv --solver-neural-liveness
12+
ebmc PWM_6.sv --solver-neural-liveness
13+
ebmc PWM_7.sv --solver-neural-liveness
14+
ebmc PWM_8.sv --solver-neural-liveness
15+
ebmc PWM_9.sv --solver-neural-liveness
16+
fi
17+
18+
if false ; then
19+
ebmc delay_1.sv --solver-neural-liveness "750-cnt"
20+
ebmc delay_2.sv --solver-neural-liveness "1250-cnt"
21+
ebmc delay_3.sv --solver-neural-liveness "2500-cnt"
22+
ebmc delay_4.sv --solver-neural-liveness "5000-cnt"
23+
ebmc delay_5.sv --solver-neural-liveness "7500-cnt"
24+
ebmc delay_6.sv --solver-neural-liveness "10000-cnt"
25+
ebmc delay_7.sv --solver-neural-liveness "12500-cnt"
26+
ebmc delay_8.sv --solver-neural-liveness "15000-cnt"
27+
ebmc delay_9.sv --solver-neural-liveness "17500-cnt"
28+
ebmc delay_10.sv --solver-neural-liveness "20000-cnt"
29+
ebmc delay_11.sv --solver-neural-liveness "22500-cnt"
30+
ebmc delay_12.sv --solver-neural-liveness "25000-cnt"
31+
ebmc delay_13.sv --solver-neural-liveness "50000-cnt"
32+
ebmc delay_14.sv --solver-neural-liveness "100000-cnt"
33+
ebmc delay_15.sv --solver-neural-liveness "200000-cnt"
34+
ebmc delay_16.sv --solver-neural-liveness "400000-cnt"
35+
fi
36+
37+
if false ; then
38+
ebmc gray_1.sv --solver-neural-liveness
39+
ebmc gray_2.sv --solver-neural-liveness
40+
ebmc gray_3.sv --solver-neural-liveness
41+
ebmc gray_4.sv --solver-neural-liveness
42+
ebmc gray_5.sv --solver-neural-liveness
43+
ebmc gray_6.sv --solver-neural-liveness
44+
ebmc gray_7.sv --solver-neural-liveness
45+
ebmc gray_8.sv --solver-neural-liveness
46+
ebmc gray_9.sv --solver-neural-liveness
47+
ebmc gray_10.sv --solver-neural-liveness
48+
ebmc gray_11.sv --solver-neural-liveness
49+
fi
50+
51+
if false ; then
52+
ebmc i2c_1.sv --solver-neural-liveness "2**9-cnt"
53+
ebmc i2c_2.sv --solver-neural-liveness "2**10-cnt"
54+
ebmc i2c_3.sv --solver-neural-liveness "2**11-cnt"
55+
ebmc i2c_4.sv --solver-neural-liveness "2**12-cnt"
56+
ebmc i2c_5.sv --solver-neural-liveness "2**13-cnt"
57+
ebmc i2c_6.sv --solver-neural-liveness "2**14-cnt"
58+
ebmc i2c_7.sv --solver-neural-liveness "2**15-cnt"
59+
ebmc i2c_8.sv --solver-neural-liveness "2**16-cnt"
60+
ebmc i2c_9.sv --solver-neural-liveness "2**17-cnt"
61+
ebmc i2c_10.sv --solver-neural-liveness "2**18-cnt"
62+
ebmc i2c_11.sv --solver-neural-liveness "2**19-cnt"
63+
ebmc i2c_12.sv --solver-neural-liveness "2**10-cnt"
64+
ebmc i2c_13.sv --solver-neural-liveness "2**10-cnt"
65+
ebmc i2c_14.sv --solver-neural-liveness "2**10-cnt"
66+
ebmc i2c_15.sv --solver-neural-liveness "2**10-cnt"
67+
ebmc i2c_16.sv --solver-neural-liveness "2**10-cnt"
68+
ebmc i2c_17.sv --solver-neural-liveness "2**10-cnt"
69+
ebmc i2c_18.sv --solver-neural-liveness "2**10-cnt"
70+
ebmc i2c_19.sv --solver-neural-liveness "2**10-cnt"
71+
ebmc i2c_20.sv --solver-neural-liveness "2**19-cnt"
72+
fi
73+
74+
if false ; then
75+
ebmc lcd_1.sv --solver-neural-liveness "{3-state,500-cnt}"
76+
ebmc lcd_2.sv --solver-neural-liveness "{3-state,1000-cnt}"
77+
ebmc lcd_3.sv --solver-neural-liveness "{3-state,1500-cnt}"
78+
ebmc lcd_4.sv --solver-neural-liveness "{3-state,2500-cnt}"
79+
ebmc lcd_5.sv --solver-neural-liveness "{3-state,5000-cnt}"
80+
ebmc lcd_6.sv --solver-neural-liveness "{3-state,7500-cnt}"
81+
ebmc lcd_7.sv --solver-neural-liveness "{3-state,10000-cnt}"
82+
ebmc lcd_8.sv --solver-neural-liveness "{3-state,12500-cnt}"
83+
ebmc lcd_9.sv --solver-neural-liveness "{3-state,15000-cnt}"
84+
ebmc lcd_10.sv --solver-neural-liveness "{3-state,17500-cnt}"
85+
ebmc lcd_11.sv --solver-neural-liveness "{3-state,20000-cnt}"
86+
ebmc lcd_12.sv --solver-neural-liveness "{3-state,22500-cnt}"
87+
ebmc lcd_13.sv --solver-neural-liveness "{3-state,90000-cnt}"
88+
ebmc lcd_14.sv --solver-neural-liveness "{3-state,180000-cnt}"
89+
fi
90+
91+
if false ; then
92+
ebmc seven_seg_1.sv --solver-neural-liveness --property SEVEN.property.p1
93+
ebmc seven_seg_2.sv --solver-neural-liveness --property SEVEN.property.p1
94+
ebmc seven_seg_3.sv --solver-neural-liveness --property SEVEN.property.p1
95+
ebmc seven_seg_4.sv --solver-neural-liveness --property SEVEN.property.p1
96+
ebmc seven_seg_5.sv --solver-neural-liveness --property SEVEN.property.p1
97+
ebmc seven_seg_6.sv --solver-neural-liveness --property SEVEN.property.p1
98+
ebmc seven_seg_7.sv --solver-neural-liveness --property SEVEN.property.p1
99+
ebmc seven_seg_8.sv --solver-neural-liveness --property SEVEN.property.p1
100+
ebmc seven_seg_9.sv --solver-neural-liveness --property SEVEN.property.p1
101+
ebmc seven_seg_10.sv --solver-neural-liveness --property SEVEN.property.p1
102+
ebmc seven_seg_11.sv --solver-neural-liveness --property SEVEN.property.p1
103+
ebmc seven_seg_12.sv --solver-neural-liveness --property SEVEN.property.p1
104+
ebmc seven_seg_16.sv --solver-neural-liveness --property SEVEN.property.p1
105+
ebmc seven_seg_17.sv --solver-neural-liveness --property SEVEN.property.p1
106+
ebmc seven_seg_18.sv --solver-neural-liveness --property SEVEN.property.p1
107+
fi
108+
109+
if false ; then
110+
ebmc thermocouple_1.sv --solver-neural-liveness "{2-state,2**5-cnt}"
111+
ebmc thermocouple_2.sv --solver-neural-liveness "{2-state,2**9-cnt}"
112+
ebmc thermocouple_3.sv --solver-neural-liveness "{2-state,2**10-cnt}"
113+
ebmc thermocouple_4.sv --solver-neural-liveness "{2-state,2**10-cnt}"
114+
ebmc thermocouple_5.sv --solver-neural-liveness "{2-state,2**11-cnt}"
115+
ebmc thermocouple_6.sv --solver-neural-liveness "{2-state,2**11-cnt}"
116+
ebmc thermocouple_7.sv --solver-neural-liveness "{2-state,2**12-cnt}"
117+
ebmc thermocouple_8.sv --solver-neural-liveness "{2-state,2**12-cnt}"
118+
ebmc thermocouple_9.sv --solver-neural-liveness "{2-state,2**13-cnt}"
119+
ebmc thermocouple_10.sv --solver-neural-liveness "{2-state,2**14-cnt}"
120+
ebmc thermocouple_11.sv --solver-neural-liveness "{2-state,2**14-cnt}"
121+
ebmc thermocouple_12.sv --solver-neural-liveness "{2-state,2**14-cnt}"
122+
ebmc thermocouple_13.sv --solver-neural-liveness "{2-state,2**15-cnt}"
123+
ebmc thermocouple_14.sv --solver-neural-liveness "{2-state,2**16-cnt}"
124+
ebmc thermocouple_15.sv --solver-neural-liveness "{2-state,2**17-cnt}"
125+
ebmc thermocouple_16.sv --solver-neural-liveness "{2-state,2**18-cnt}"
126+
ebmc thermocouple_17.sv --solver-neural-liveness "{2-state,2**19-cnt}"
127+
fi
128+
129+
if false ; then
130+
ebmc uart_transmit_1.sv --solver-neural-liveness --trace-steps 100 --traces 20
131+
ebmc uart_transmit_2.sv --solver-neural-liveness --trace-steps 100 --traces 20
132+
ebmc uart_transmit_3.sv --solver-neural-liveness --trace-steps 100 --traces 20
133+
ebmc uart_transmit_4.sv --solver-neural-liveness --trace-steps 100 --traces 20
134+
ebmc uart_transmit_5.sv --solver-neural-liveness --trace-steps 100 --traces 20
135+
ebmc uart_transmit_6.sv --solver-neural-liveness --trace-steps 100 --traces 20
136+
ebmc uart_transmit_7.sv --solver-neural-liveness --trace-steps 100 --traces 20
137+
ebmc uart_transmit_8.sv --solver-neural-liveness --trace-steps 100 --traces 20
138+
ebmc uart_transmit_9.sv --solver-neural-liveness --trace-steps 100 --traces 20
139+
ebmc uart_transmit_10.sv --solver-neural-liveness --trace-steps 200 --traces 20
140+
ebmc uart_transmit_11.sv --solver-neural-liveness --trace-steps 200 --traces 20
141+
ebmc uart_transmit_12.sv --solver-neural-liveness --trace-steps 200 --traces 20
142+
fi
143+
144+
if false ; then
145+
ebmc vga_1.sv --solver-neural-liveness "{2**5-v_cnt,2**7-h_cnt}"
146+
ebmc vga_2.sv --solver-neural-liveness "{2**6-v_cnt,2**8-h_cnt}"
147+
ebmc vga_3.sv --solver-neural-liveness "{2**6-v_cnt,2**8-h_cnt}"
148+
ebmc vga_4.sv --solver-neural-liveness "{2**7-v_cnt,2**9-h_cnt}"
149+
ebmc vga_5.sv --solver-neural-liveness "{2**8-v_cnt,2**9-h_cnt}"
150+
ebmc vga_6.sv --solver-neural-liveness "{2**8-v_cnt,2**9-h_cnt}"
151+
ebmc vga_7.sv --solver-neural-liveness "{2**8-v_cnt,2**10-h_cnt}"
152+
ebmc vga_8.sv --solver-neural-liveness "{2**9-v_cnt,2**10-h_cnt}"
153+
ebmc vga_9.sv --solver-neural-liveness "{2**9-v_cnt,2**11-h_cnt}"
154+
fi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
counter1.sv
3+
--traces 1 --solver-neural-liveness
4+
^weight: nn::fc1\.n0\.w0 = 1$
5+
^bias: nn::fc1\.n0\.b = .*$
6+
^\[main\.property\.p0\] always s_eventually main\.counter == 0: PROVED$
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// count down from 10 to 0
2+
3+
module main(input clk);
4+
5+
reg [7:0] counter;
6+
7+
initial counter = 10;
8+
9+
always @(posedge clk)
10+
if(counter != 0)
11+
counter = counter - 1;
12+
13+
// expected to pass
14+
p0: assert property (s_eventually counter == 0);
15+
16+
endmodule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
wrap_around1.sv
3+
--traces 1 --solver-neural-liveness
4+
^weight: nn::fc1\.n0\.w0 = -1$
5+
^bias: nn::fc1\.n0\.b = .*$
6+
^\[main\.property\.p0\] always s_eventually main\.counter == 10: PROVED$
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// count up from 0 to 10
2+
3+
module main(input clk);
4+
5+
reg [7:0] counter;
6+
7+
initial counter = 0;
8+
9+
always @(posedge clk)
10+
if(counter == 10)
11+
counter = 0;
12+
else
13+
counter = counter + 1;
14+
15+
// expected to pass
16+
p0: assert property (s_eventually counter == 10);
17+
18+
endmodule

src/ebmc/Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ SRC = \
2323
output_verilog.cpp \
2424
random_traces.cpp \
2525
ranking_function.cpp \
26+
ranking_net.cpp \
2627
report_results.cpp \
2728
show_formula_solver.cpp \
2829
show_properties.cpp \
2930
show_trans.cpp \
31+
solver_neural_liveness.cpp \
3032
transition_system.cpp \
3133
waveform.cpp \
3234
#empty line

src/ebmc/ebmc_parse_options.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Author: Daniel Kroening, [email protected]
2525
#include "random_traces.h"
2626
#include "ranking_function.h"
2727
#include "show_trans.h"
28+
#include "solver_neural_liveness.h"
2829

2930
#include <iostream>
3031

@@ -162,6 +163,9 @@ int ebmc_parse_optionst::doit()
162163
if(cmdline.isset("neural-liveness"))
163164
return do_neural_liveness(cmdline, ui_message_handler);
164165

166+
if(cmdline.isset("solver-neural-liveness"))
167+
return do_solver_neural_liveness(cmdline, ui_message_handler);
168+
165169
if(cmdline.isset("ranking-function"))
166170
return do_ranking_function(cmdline, ui_message_handler);
167171

src/ebmc/ebmc_parse_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class ebmc_parse_optionst:public parse_options_baset
3434
"(po)(cegar)(k-induction)(2pi)(bound2):"
3535
"(outfile):(xml-ui)(verbosity):(gui)(json-result):"
3636
"(neural-liveness)(neural-engine):"
37+
"(solver-neural-liveness)"
3738
"(reset):"
3839
"(version)(verilog-rtl)(verilog-netlist)"
3940
"(compute-interpolant)(interpolation)(interpolation-vmcai)"

src/ebmc/ebmc_solver_factory.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Author: Daniel Kroening, [email protected]
1616
#include <solvers/decision_procedure.h>
1717
#include <solvers/prop/prop.h>
1818

19-
#include <iosfwd>
19+
#include <fstream>
2020
#include <memory>
2121

2222
class ebmc_solvert final

src/ebmc/ranking_net.cpp

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*******************************************************************\
2+
3+
Module: Ranking Neural Net
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "ranking_net.h"
10+
11+
#include <util/arith_tools.h>
12+
#include <util/bitvector_types.h>
13+
#include <util/std_expr.h>
14+
15+
exprt wrap_around(exprt expr)
16+
{
17+
// map negative values to positive ones, wrap around:
18+
// -1 --> int_max-1, -2 --> int_max-2, etc.
19+
auto int_max = to_signedbv_type(expr.type()).largest_expr();
20+
return if_exprt{sign_exprt{expr}, plus_exprt{int_max, expr}, expr};
21+
}
22+
23+
tuple_exprt wrap_around_tuple(tuple_exprt expr)
24+
{
25+
// map negative values to positive ones, wrap around:
26+
// -1 --> int_max-1, -2 --> int_max-2, etc.
27+
for(auto &op : expr.operands())
28+
op = wrap_around(op);
29+
30+
return expr;
31+
}
32+
33+
tuple_exprt ranking_nett::forward(const tuple_exprt &inputs) const
34+
{
35+
auto fc1_out = fc1.forward(inputs);
36+
auto w_out = wrap_around_tuple(fc1_out);
37+
return w_out;
38+
}
39+
40+
ranking_nett::lineart::lineart(
41+
const irep_idt &__name,
42+
std::size_t in,
43+
std::size_t out,
44+
const typet &type)
45+
: name(__name)
46+
{
47+
neurons.reserve(out);
48+
49+
for(std::size_t i = 0; i < out; i++)
50+
{
51+
irep_idt identifier = id2string(__name) + ".n" + std::to_string(i);
52+
neurons.emplace_back(identifier, in, type);
53+
}
54+
}
55+
56+
ranking_nett::lineart::neuront::neuront(
57+
const irep_idt &__name,
58+
std::size_t in,
59+
const typet &type)
60+
: name(__name)
61+
{
62+
{
63+
irep_idt identifier = id2string(__name) + ".b";
64+
bias = symbol_exprt(identifier, type);
65+
}
66+
67+
weights.reserve(in);
68+
69+
for(std::size_t i = 0; i < in; i++)
70+
{
71+
irep_idt identifier = id2string(__name) + ".w" + std::to_string(i);
72+
weights.emplace_back(symbol_exprt{identifier, type});
73+
}
74+
}
75+
76+
exprt ranking_nett::lineart::neuront::forward(const tuple_exprt &input) const
77+
{
78+
exprt::operandst result;
79+
result.reserve(weights.size() + 1); // one more for bias
80+
81+
result.push_back(bias);
82+
83+
PRECONDITION(weights.size() == input.operands().size());
84+
85+
for(std::size_t i = 0; i < weights.size(); i++)
86+
result.push_back(mult_exprt{weights[i], input.operands()[i]});
87+
88+
return plus_exprt{std::move(result), bias.type()};
89+
}
90+
91+
exprt relu(exprt expr)
92+
{
93+
auto zero = from_integer(0, expr.type());
94+
return if_exprt{greater_than_or_equal_exprt{expr, zero}, expr, zero};
95+
}
96+
97+
tuple_exprt ranking_nett::lineart::forward(const tuple_exprt &input) const
98+
{
99+
tuple_exprt::operandst result;
100+
result.reserve(neurons.size());
101+
102+
for(auto &neuron : neurons)
103+
result.push_back(neuron.forward(input));
104+
105+
return tuple_exprt{std::move(result)};
106+
}

0 commit comments

Comments
 (0)