vale1410 / bule Goto Github PK
View Code? Open in Web Editor NEWThe SAT and QBF Programming Language Bule
License: Other
The SAT and QBF Programming Language Bule
License: Other
Consider the following program.
test[-1].
test[X] :: do(1+X).
I would expect it to ground to do(0)
, instead, I get a syntax error about invalid token '+-'
Consider the command bule solve file1.bul file2.bul
. If there is an error in file2.bul, the line reported will off by the number of lines in file1
> bule ipc_2000_blocks_10_11.bul
grounds successful whereas:
> bule ipc_2000_blocks_10_12.bul
Warning. Grounding predicate type used in a rule without being defined anywhere.
Fatal error: exception Stack overflow
For certain errors Bule does not output info needed for tracing the problem like line number and file name.
Example:
File:
#ground a[12].
a[Y] :: #ground b[X].
running Bule outputs:
Fatal error: exception Bule2.Circuit.UnboundVar("X")
missing line number and more.
when running bule2 --solve --models 0 graph_colouring_basic.bul
wtih unchanged graph_colouring_basic.bul
output is
Instance ground. Starts solving
SAT
Model 1: ~set_a_blue ~set_a_green ~set_a_red ~set_e_blue ~set_e_green ~set_e_red
If running bule2 --solve --models 0 graph_colouring_basic.bul --solver minisat
, the output is as expected
Instance ground. Starts solving
SAT
Model 1: ~set_a_blue ~set_a_green set_a_red ~set_e_blue set_e_green ~set_e_red
Model 2: ~set_a_blue ~set_a_green set_a_red set_e_blue ~set_e_green ~set_e_red
Model 3: ~set_a_blue set_a_green ~set_a_red ~set_e_blue ~set_e_green set_e_red
Model 4: ~set_a_blue set_a_green ~set_a_red set_e_blue ~set_e_green ~set_e_red
Model 5: set_a_blue ~set_a_green ~set_a_red ~set_e_blue set_e_green ~set_e_red
Model 6: set_a_blue ~set_a_green ~set_a_red ~set_e_blue ~set_e_green set_e_red
No more models. Total: 6 displayed models out of 6 models.
Distinguish correctly:
bule dimacs
(to be piped to a SAT or QBF Solver)bule ground
(for debugging with textual output)Currently the std.output of the solvers is piped to stderr from bule. Fix.
I'd like to be able to write #E[T] :: var[T]
as an alternative to #exists[T] :: var[T]
, same with #A[T]
instead of #forall[T]
. This is shorter and no less readable because we are used to
bule dimacs sample.bul
returns
c dimacs grounding called.
prepare with args
p cnf 10 2
e 5 8 9 2 3 4 6 7 10 11 0
dom[c]. | .
#exists | [0] | | all[X] | | all[Y] | | dom[Z] | :: | q(X | Y | Z)?.
the sample.bul file contains:
dom[a].
dom[b].
dom[c].
mom[d].
mom[e].
dom[X] :: all[X].
mom[X] :: all[X].
#exists [0], all[X], all[Y], dom[Z] :: q(X,Y,Z)?
dom[X], mom[Y] :: dom[Z] : q(X,Y,Z).
dom[X], dom[Y] :: q(X,Y,c) | q(Y,X,b).
do it
Problem: Given a ground clause it can be hard to find out from which Bule rule it came from. I start to comment out Rules and see how the ground program changes.
Easy and very useful information:
Before every set of ground clauses display the original Bule Rule in a comment
For example, this program:
#ground dom[1], dom[2], dom[3].
dom[X] :: #forall[X] varA(X).
dom[X] :: #exists[X] varE(X).
dom[A] :: varA(A) | dom[E] : varE(E).
dom[E],dom[A] :: ~varE(E) | varA(A).
The result from bule test.bul --origin
would be:
%% dom[X] :: #forall[X] varA(X).
%% generates 3 universal variables
%% dom[X] :: #exists[X] varE(X).
%% generates 3 existential variables
#forall[0] varA(1).
#exists[1] varE(1).
#forall[2] varA(2).
#exists[3] varE(2).
#forall[4] varA(3).
#exists[5] varE(3).
%% dom[A] :: varA(A) | dom[E] : varE(E).
%% grounds to 3 clauses:
varA(1) | varE(1) | varE(2) | varE(3).
varA(2) | varE(1) | varE(2) | varE(3).
varA(3) | varE(1) | varE(2) | varE(3).
%% dom[E],dom[A] :: ~varE(E) | varA(A).
%% grounds to 9 clauses:
~varE(1) | varA(1).
~varE(1) | varA(2).
~varE(1) | varA(3).
~varE(2) | varA(1).
~varE(2) | varA(2).
~varE(2) | varA(3).
~varE(3) | varA(1).
~varE(3) | varA(2).
~varE(3) | varA(3).
Hello!
So in the instructions for set up, commands such as bule list and bule add is not working. Specifically, the error message is:
Command 'bule' not found, did you mean:
command 'buble' from deb node-buble (0.19.8-8)
Try: sudo apt install
I know that the commands are stored in cmd directory but how can I install bule to make it source these files?
The following code grounds fine, but it shouldn't.
#exists[0] :: a?
#forall[1] :: a?
#exists[2] :: c?
a | c.
Same story with
#exists[0] :: a?
#forall[1] :: c?
#exists[2] :: a?
a | c.
%% %% %%% Problem with negation and _ :
%% val[X], ~map[_,X] :: debug[X].
Minisiat is provided for pure SAT formulas, but Bule2 can only generate DIMACS for QBF formulas and cannot drive a solver. It is desirable to have a solver embedded to be able to nicely print the models.
This will facilitate debugging.
Many unix commands can read their input from the standard input channel. It would be nice for bule to allow that too.
For example cat file1.bul file2.bul | bule file3.bul
or, alternatively use -
as a signal for stdin reading cat file1.bul file2.bul | bule file3.bul -
.
(this is not so useful with piping from cat
as bule can take many files as input already, but it can be useful with grep
or bule2 input).
Something similar to assertions in other languages, for instance running bule2 on the following code
:: dom[X], bad[X] :: #fail.
dom[1..3].
bad[3..5].
should produce an error message (because of X=3
) and stop grounding. This makes it possible to detect errors in the grounding process or in parameters files.
Similarly, we could introduce a dual keyword for grounding that needs to take place.
:: dom[X], need[X] :: #required.
dom[1..3].
need[1..4].
should produce an error message because of X=4
missing.
literals eliminated during unit propagation are not presenit in the bule solve model.
Running bule2 --solve --models 0 test.bule2
on file containing:
#exists[0] x.
#exists[0] y.
#exists[0] z.
x | y.
~z.
Returns the following output:
Model 1: ~x y ~z
Model 2: x ~y ~z
Model 3: x y ~z
I would like bule2 option so that the output is:
Model 1: y
Model 2: x
Model 3: x y
Currently, following program
#ground v(1).
results in this error message:
Fatal error: exception Invalid_argument("Parser error. In file error.bul, at line 6, column 9: syntax error. <YOUR SYNTAX ERROR MESSAGE HERE>\n (error 56)")
Better error message:
Line 1, wrong usage of parenthesis for extensional atom. Please use brackets.
Dual to issue #34 , but it's not clear to me in the universal case whether the variables should be going outermost or second innermost before the existential one.
The following snippet is converted to incorrect qdimacs (with variable v appearing twice in the block) and causes issues in the solver.
#ground p[x], p[y].
p[A] :: #exists v.
v.
~v.
dom[a].
dom[b].
dom[c].
mom[d].
mom[e].
dom[X] :: all[X].
mom[X] :: all[X].
#exists [0], all[X], all[Y], dom[Z] :: q(X,Y,Z)?
q(c,e,c).
dom[X], mom[Y] :: dom[Z] : q(X,Y,Z).
dom[X], dom[Y] :: q(X,Y,c) | q(Y,X,b).
In this code block, I have explicitly mentioned q(c,e,c) to be true but it comes out to be false. This isn't just the case here, it happens every time. Single literals are not getting implemented correctly.
bule solve sample.bul return :
C program grounded in 32.605973ms.
This is a QBF problem
Using a QBF solver instance 'depqbf --no-dynamic-nenofex --qdo'
Solving. . .
-------- Solver output -----
2021/06/12 12:04:01 solver>> s cnf 1 75 15
-------- Solver output end -----
s SAT
--------
~q(c,e,c).
q(c,d,c).
q(c,c,c).
q(c,b,c).
~q(a,d,a).
~q(a,e,a).
q(c,a,c).
q(b,e,c).
q(b,d,c).
~q(b,d,a).
~q(b,e,a).
q(b,c,c).
q(b,b,c).
q(b,a,c).
~q(c,d,a).
~q(c,e,a).
q(a,e,c).
q(a,d,c).
q(a,c,c).
q(a,b,c).
q(a,a,c).
q(c,e,b).
~q(c,d,b).
~q(c,c,b).
~q(c,b,b).
~q(c,a,b).
~q(a,a,b).
~q(a,b,b).
~q(a,c,b).
~q(a,d,b).
~q(a,e,b).
~q(b,a,b).
~q(b,b,b).
~q(b,c,b).
~q(b,d,b).
~q(b,e,b).
--------
Comments for solvers are improperly handled.
Modified bule2/lib/Solve.ml to fix the issue:
Below is the code from line 24:
let input_lines inp =
let l = ref [] in
(try
while true do l := input_line inp :: !l done
with End_of_file -> ());
List.rev !l
let isnt_comment line =
String.length line > 0 && line.[0] <> 'c'
let run_process cmd dimacs =
let inp, out = Unix.open_process cmd in
fprintf out "%s%!" (Dimacs.Print.qbf_file dimacs);
close_out out;
let lines = input_lines inp in
close_in inp;
let lines = List.filter isnt_comment lines in
parse_output lines
n[1].
n[2].
n[2*X] :: m[X].
should ground to n[1].n[2].m[1]
.
There is a way around it by just adding a domain predicate for the variables to be solved:
Consider the following program.
bar[a]. bar[b].
bar[X], bar[Y] :: foo[X,Y].
foo[X,_] :: var(X).
Bule grounds it to
var(a). var(a). var(b). var(b).
Whereas
var(a). var(b).
would be preferable.
This issue is similar to #26 (comment)
#ground d_t[a, f(a)].
#ground d_t[b, f(b)].
d_t[X, f(X)] :: m(X).
produces no grounding result. By changing the clause to:
d_t[X, f(X_1)], X == X_1 :: m(X).
We get the grounding result
m(a).
m(b).
This program generate 360000 facts, but gets a stackoverflow error when called with --facts
#ground p[1..600].
p[X], p[Y] :: #ground q[X,Y,X+Y].
with p[1..500] it manages to ground and print the facts.
For example dom[1..3].
should be #ground dom[1..3]
. Not sure if this is intentional or not.
Happy to make a PR to update syntax in the syntax section to bule2 if needed.
following program gives an error message: Fatal error: exception Failure("Error: variable X is unbound in an arithmetical expression when grounding p[X \\+ 1].")
#ground p[1], t[2].
p[X+1], p[X] :: #ground q[X].
it works correctly if order in the generator is swapped:
#ground p[1], t[2].
p[X], p[X+1] :: #ground q[X].
The following snippet creates a panic error in bule.
#exists[0] :: assign(1,1,1,2)? #exists[0] :: assign(1,1,1,1)?
~assign(1,1,1,2) | ~assign(1,1,1,1).
assign(1,1,1,2) | assign(1,1,1,1).
similar for #forall second to innermost level of #exists
Allow for simple Implications =>
in the Clause. Left part of implication is separated by & , and right party by | .
Iterators ground straight forward generate & on the left, and | on the right. Only one level term rewriting.
rule :: <generator> <RuleSep> <iterator> ( <AND> <iterator> ) * <Implication> <iterator> ( <OR> <iterator> )* <EndRule>
<generator> :: <factOrConstraint> ( , <factOrConstraint>)
<iterator> :: <factOrConstraint> ( , <factOrConstraint>) : <literal>
literal :: (~ | <atom>)
dom[1].dom[2].
dom[X], dom[Y], X==Y ::
~q(X) &
dom[X], dom[Y], X > Y : vale(X)
->
q(Y) |
dom[Z] : r(Y,Z).
Thanks to
@AbdallahS
Introduce more show command-line options, like show positive, show all, show none.
For given grounding files, and a given model not satisfying the corresponding formula, identify which clauses are not satisfied by the model. Ideally, we would also identify the lifted clauses.
this is old:
#exists[0] :: set(e,red)?
#exists[0] :: set(e,green)?
should be :
#exists[0] set(e,red).
#exists[0] set(e,green).
and with issue ... it could be:
#exists set(e,red).
#exists set(e,green).
Given the following Bule2 example:
d_colored[va].
d_colored[vb].
d_colored1[color(va, red)].
d_colored1[color(vb, red)].
:: d_colored[Vv] :: colored(Vv) -> : d_colored1[color(Vv, Vc)] : colored1(color(Vv, Vc)).
It produces the grounding result:
colored(va) -> .
colored(vb) -> .
The expected grounding would be:
colored(va) -> colored1(color(va, red)).
colored(vb) -> colored1(color(vb, red)).
By changing the Bule2 rule to:
:: d_colored[Vv] :: colored(Vv) -> : d_colored1[color(V1, Vc)], V1 == Vv : colored1(color(V1, Vc)).
The grounding produces the expected result. This problem appears to only happen with variables within functions. e.g.
The following program should not generate any unit clauses:
#ground f[1],f[2],f[3].
f[X] :: var(X).
Bule grounds this to:
Warning. Undeclared variables: var(1) var(2) var(3)
var(1).
var(2).
var(3).
It's good that it notifies that clauses are generated of which no variables are introduced.
In my opinion it should not generate the clauses at all.
For example:
#ground f[1],f[2].
f[X] :: #exists[0] foo(X).
f[X] :: bar(X) | foo(X).
In my opinion it should not generate the clauses.
Alternative option: it generates the clauses with the atoms that have been introduced.
It would be great if there could be a mapping from strings to integer in the comments of the dimacs file in order to make it more readable.
Examples;
fact[B], literal(B).
instead of
fact[B] : literal(B).
bule --version or bule version should provide the current version.
we would like something like
Q:=1..4 :: #ground dom[Q].
The bule syntax for version 4 does not have ?
anymore.
following bule program
#exists[0] v(1).
with running bule on it gives:
#exists[0] :: v(1)?
should not return with question mark.
bule --version
has no output
The following code shouldn't solve/ground at all because there is no final full stop after a[0].
a[1].
#exists[0], a[X] :: var(X)?
a[X]:: var(X).
a[0]
Currently there is just a #hide
command which stops search variables front being show in stdout when solving / grounding.
It would be helpful to have a #show
command where only variables with #show
in front of them are shown.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.