Kodkodi 1.1.4 (March 17, 2009) is a front-end for the Java library Kodkod, a SAT-based solver for first-order logic with relations, transitive closure, and partial instances. Kodkod forms the basis of Alloy Analyzer version 4. The Kodkodi front-end is designed to make the Kodkod library available to other programming languages than Java. Kodkodi is developed and maintained by Jasmin Christian Blanchette at the Technische Universität München.
Kodkodi requires the runtimes for ANTLR 3.1.1 and the Nov. 27, 2008 version of Kodkod to be located in the Java classpath. Both are bundled with Kodkodi. In addition, you will need to install a SAT solver. Follow the instructions on Kodkod's home page, or use the platform-independent (but apparently slower) SAT4J solver bundled with Kodkodi. To run the program, you simply need a Java 1.5 virtual machine (normally called java). To recompile it, you need a Java compiler and the ANTLR parser generator tools.
The kodkodi program takes its input from standard input and writes its output to standard output (on success) or standard error (on failure). Examples are provided in the examples directory.
Usage: kodkodi [options] options: -help Show usage and exit -verbose Produce more output -exit-on-success Exit on the first successful 'solve' directive -clean-up-inst Remove trivial parts of instance from output -max-msecs <num> Maximum running time in milliseconds -max-threads <num> Maximum number of simultaneous threads
Example:
$ java de.tum.in.isabelle.Kodkodi.Kodkodi < examples/pigeonhole.kki *** PROBLEM 1 *** ---OUTCOME--- UNSATISFIABLE ---STATS--- p cnf 54 68 primary variables: 6 parsing time: 65 ms translation time: 92 ms solving time: 0 ms
Kodkodi's input format borrows heavily from the output format of the toString() implementations found in the Kodkod library. The operator that are available in Alloy 4 are given the same precedences as they have there.
The grammar is expressed using a variant of Extended Backus-Naur Form (EBNF). The actual grammar used by Kodkodi is written using ANTLR and can be found in the file Kodkodi.g.
The grammar is based on the following lexical units, or tokens:
WHITESPACE ::= ( | \n | \r | \t | \v)+ COMMENT ::= // ~(\n)* (\n | EOF) NUM ::= [+ | -] (0 | 1 | … | 9)+ STR_LITERAL ::= " ~(" | \n)* " ATOM_NAME ::= A NAT UNIV_NAME ::= u NAT OFF_UNIV_NAME ::= u NAT @ NAT TUPLE_NAME ::= (P | T NAT _) NAT RELATION_NAME ::= (s | r | m NAT _) NAT VARIABLE_NAME ::= (S | R | M NAT _) NAT '? TUPLE_REG ::= $ (A | P | T NAT _) NAT TUPLE_SET_REG ::= $ (a | p | t NAT _) NAT FORMULA_REG ::= $f NAT REL_EXPR_REG ::= $e NAT INT_EXPR_REG ::= $i NAT
NAT abbreviates 0 | 1..9 0..9*.
Comments start with // and end with the line. Whitespace is ignored, except as a token separator. In addition to the tokens listed above, various keywords and operators are recognized as tokens. These are shown in bold in the grammar.
The table below describes the lexical conventions adopted for naming atoms, tuples, relations, variables, and registers.
Token Name | Syntax | Description |
ATOM_NAME | Aj | Atom at index j in the universe |
UNIV_NAME | un | Set of atoms A0 to A(n − 1) |
OFF_UNIV_NAME | un@j | Set of atoms Aj to A(j + n − 1) |
TUPLE_NAME | Pj | Pair at index j in the pair space associated with the universe |
Tn_j | n-tuple at index j in the n-tuple space associated with the universe (n ≥ 3) | |
RELATION_NAME | sj | Set number j |
rj | Binary relation number j | |
mn_j | n-ary multirelation number j (n ≥ 3) | |
VARIABLE_NAME | Sj | Unprimed set variable number j |
Sj' | Primed set variable number j | |
Rj | Unprimed binary relation variable number j | |
Rj' | Primed binary relation variable number j | |
Mn_j | Unprimed n-ary multirelation variable number j (n ≥ 3) | |
Mn_j' | Primed n-ary multirelation variable number j (n ≥ 3) | |
TUPLE_REG | $Aj | One-tuple register number j |
$Pj | Pair register number j | |
$Tn_j | n-tuple register number j (n ≥ 3) | |
TUPLE_SET_REG | $aj | One-tuple set register number j |
$pj | Pair set register number j | |
$tn_j | n-tuple set register number j (n ≥ 3) | |
FORMULA_REG | $fj | Formula register number j |
REL_EXPR_REG | $ej | Relational expression register number j |
INT_EXPR_REG | $ij | Integer expression register number j |
Atoms and tuples are defined implicitly in terms of the universe. Relations and variables need no declarations, but relations do need bounds. Variables may be primed—a primed variable is distinct from the corresponding unprimed variant. Registers must be assigned to before they are used in an expression. It is highly recommended to use low indices because Kodkodi stores relations, variables, and registers in 0-based arrays.
This section presents the overall structure of Kodkod input files.
problems ::= problem*
Kodkodi takes a list of “problems” as input.
problem ::= option* univ_spec tuple_reg_directive* bound_spec* int_bound_spec? expr_reg_directive* solve_directive
A problem consists of three main parts: a universe specification, a set of bound specifications, and a Kodkod formula to satisfy supplied in a “solve” directive.
Example:
univ: u1 bounds s0: {A0} solve all [S0 : one s0, S1 : one s0] | S0 = S1;
option ::= solver : STR_LITERAL (, STR_LITERAL)* | symmetry_breaking : NUM | sharing : NUM | bit_width : NUM | skolem_depth : NUM | flatten : (true | false)
Kodkod supports various options, documented in the kodkod.engine.config.Options class. The following solvers are supported:
solver: "DefaultSAT4J" solver: "LightSAT4J" solver: "ZChaff" solver: "zChaff" solver: "ZChaffMincost" solver: "zChaffMincost" solver: "MiniSatProver" solver: "MiniSat" solver: "SAT4J" "instance" solver: "External" "executable" "temp_input" "temp_output" "arg_1" … "arg_n" solver: "ExternalV2" "executable" "temp_input" "temp_output" "sat_marker" "var_marker" "unsat_marker" "arg_1" … "arg_n"
For "External", the optional arguments "arg_1" … "arg_n are passed before the input file name. For "ExternalV2", they are passed after.
univ_spec ::= univ : UNIV_NAME
The universe specification fixes the universe's uninterpreted atoms. Kodkodi requires that the atoms are numbered consecutively from A0 to A(n − 1).
Examples:
univ: u2 univ: u100
bound_spec ::= bounds RELATION_NAME (, RELATION_NAME) : ( tuple_set | [ tuple_set , tuple_set ] )
A relational bound specification gives a lower and an upper bound for the given relations. If only one bound is specified, it is taken as both lower and upper bound. The lower bound must be a subset of the upper bound.
Examples:
bounds s0: {A0} bounds r2: [{}, {A0 .. A9} -> {A10 .. A19}]
int_bound_spec ::= int_bounds : int_bound_seq (, int_bound_seq)* int_bound_seq ::= [NUM :] [ tuple_set (, tuple_set)* ]
An integer bound specification establishes a correspondence between integers and sets of atoms that represent that integer in relational expressions. The syntax makes it possible to specify the bounds of consecutive integers in sequence.
Example:
int_bounds: [{A0}, {A1}], 10: [{A2}, {A3}, {A4}]
In the above example, 0 is bounded by {A0}, 1 is bounded by {A1}, 10 is bounded by {A2}, 11 is bounded by {A11}, and 12 is bounded by {A4}.
solve_directive ::= solve formula ;
The “solve” directive tells Kodkod to try to satisfy the given formula.
Example:
solve all [S0 : one s0, S1 : one s0] | !(S0 = S1) => no (S0.r0 & S1.r0)
Registers make it possible to use a complex syntactic construct several times without duplicating it. They also help reduce Kodkod's memory usage and running time.
tuple_reg_directive ::= TUPLE_REG := tuple | TUPLE_SET_REG := tuple_set
A tuple register directive assigns a value to a tuple or tuple set register.
Examples:
$P0 := [A0, A0] $P1 := [A1, A1] $t4_0 := {$P0, $P1} -> {$P0, $P1}
expr_reg_directive ::= FORMULA_REG := formula | REL_EXPR_REG := rel_expr | INT_EXPR_REG := int_expr
Formulas, relational expressions, and integer expressions can also be assigned to registers using an expression register directive. An alternative is to use the let binder inside an expression.
Examples:
$f0 := all [S0 : one s0] | s0 in univ $e5 := (s0 & s1).r1 + (s0 & s2).r2 $i14 := 2 * #($e5) + 1
Kodkod supports partial solutions in the form of bounds on relations. The bound specifications involve tuples and tuple sets.
tuple ::= [ ATOM_NAME (, ATOM_NAME)* ] | ATOM_NAME | TUPLE_NAME | TUPLE_REG
An n-tuple is normally specified using the syntax [Aj1, …, Ajn]. The brackets are optional when n = 1. Alternatively, tuples can be specified using an index in the n-tuple space. For example, given the universe {A0 .. A9}, the name P27 refers to the pair [A2, A7].
Examples:
[A0, A1, A5, A20] A0 P5 $P14
tuple_set ::= tuple_set (+ | -) tuple_set | tuple_set & tuple_set | tuple_set -> tuple_set | tuple_set [ NUM ] | { tuple (, tuple)* } | { tuple .. tuple } | { tuple # tuple } | none | all | UNIV_NAME | OFF_UNIV_NAME | TUPLE_SET_REG | ( tuple_set )
Tuple sets can be constructed in several ways. The +, -, and & operators denote the union, difference, and intersection of two tuple sets, respectively. The -> operator denotes the Cartesian product of two tuple sets. The [] operator projects the tuple set onto the given dimension. Tuple sets can be specified exhaustively by listing all their tuples. If all the tuples have consecutive indices, the range operator .. can be used. Alternatively, if all the tuples occupy a rectangular, cubic, etc., area in the tuple space, they can be specified by passing the lowest and highest corner of the area to the # operator. Finally, none is a synonym for {}, and all denotes the complete tuple set (whose arity is deduced from the context).
Examples:
{A1} {A1, A2} -> {A3, A4} {[A1, A2] .. [A3, A4]} {[A1, A2] # [A3, A4]} $p14
The operator precedences and associativities are given in the table below. Fully bracketed operators are not listed.
Level | Operator Class | Arity | Associativity |
1 | + - | Binary | Left-associative |
2 | & | Binary | Associative |
3 | -> | Binary | Associative |
4 | [] | Binary | Left-associative |
Kodkod supports three types of expression: Boolean expressions (formulas), relational expressions, and integer expressions.
formula ::= (all | some) decls | formula | let assigns | formula | if formula then formula else formula | formula || formula | formula <=> formula | formula => formula | formula && formula | ! formula | ACYCLIC ( RELATION_NAME ) | FUNCTION ( RELATION_NAME , rel_expr -> (ONE | LONE) rel_expr ) | TOTAL_ORDERING ( RELATION_NAME , (UNIV_NAME | OFF_UNIV_NAME | RELATION_NAME) , (ATOM_NAME | RELATION_NAME) , (ATOM_NAME | RELATION_NAME) ) | rel_expr (in | =) rel_expr | int_expr (= | < | <= | > | >=) int_expr | (no | lone | one | some) rel_expr | false | true | FORMULA_REG | ( formula )
A formula, or Boolean expression, specifies a constraint involving relations and integers.
Example:
some [S0 : some s0] | if S0 in s1 then !$f1 else $i0 <= $i1
rel_expr ::= let assigns | rel_expr | if formula then rel_expr else rel_expr | rel_expr (+ | -) rel_expr | rel_expr ++ rel_expr | rel_expr & rel_expr | rel_expr -> rel_expr | rel_expr \ rel_expr | rel_expr ( rel_expr (, rel_expr)* ) | rel_expr [ int_expr (, int_expr)* ] | rel_expr . rel_expr | (^ | * | ~) rel_expr | { decls | formula } | (Bits | Int) [ int_expr ] | iden | ints | none | univ | ATOM_NAME | UNIV_NAME | OFF_UNIV_NAME | RELATION_NAME | VARIABLE_NAME | REL_EXPR_REG | ( rel_expr )
A relational expression denotes a relation (set, binary relation, or multirelation). Nearly all operators are identical to those offered by Kodkod, which in turn are modeled after those provided by Alloy. Notable exceptions are the conditional expression if … then … else …; the r\s operator, which is a shorthand for if no r then s else r; and finally r(s1, …, sn), which is equivalent to sn.(…(s1.r)…).
Example:
if #(s0) > 5 then s0.r0 + s1.r1 else none
int_expr ::= sum decls | int_expr | let assigns | int_expr | if formula then int_expr else int_expr | int_expr (<< | >> | >>>) int_expr | int_expr (+ | -) int_expr | int_expr (* | / | %) int_expr | (# | sum) ( rel_expr ) | int_expr | int_expr | int_expr ^ int_expr | int_expr & int_expr | (~ | - | abs | sgn) int_expr | NUM | INT_EXPR_REG | ( int_expr )
An integer expression denotes an integer.
Example:
(sum [S0 : one s0] | #(S0) * (#(S0) + 1) / 2) % 10
decls ::= [ decl (, decl)* ] decl ::= VARIABLE_NAME : (no | lone | one | some | set) rel_expr
The all, some, and sum quantifiers take a list of variable declarations.
Example:
[S0 : set s0, S1 : one s1]
assigns ::= [ assign (, assign)* ] assign ::= FORMULA_REG := formula | REL_EXP_REG := rel_exp | INT_EXP_REG := int_exp
The let binder takes a list of register assignments.
Example:
[$f0 := all [S0 : one s0] | s0 in univ, $i14 := 2 * #($e5) + 1]
The operator precedences and associativities are given in the table below. Fully bracketed operators are not listed.
Level | Operator Class | Arity | Associativity |
1 | all | some | sum | let | if then else | Binary/Ternary | Right-associative |
2 | || | Binary | Associative |
3 | <=> | Binary | Associative |
4 | => | Binary | Right-associative |
5 | && | Binary | Associative |
6 | ! | Unary | N/A |
7 | in = < <= > >= | Binary | N/A |
8 | no lone one some | Unary | N/A |
9 | << >> >>> | Binary | Left-associative |
10 | + - | Binary | Left-associative |
11 | * / % | Binary | Left-associative |
12 | ++ | Binary | Associative |
13 | | ^ & | Binary | Associative |
14 | -> | Binary | Associative |
15 | \ | Binary | Associative |
16 | (,) | Binary | Left-associative |
17 | [,] | Binary | Left-associative |
18 | . | Binary | Left-associative |
19 | ^ * ~ - abs sgn | Unary | N/A |
Comments may be specified as in C++, that is, either as a one line comment starting with // or as a block starting with /* and ending with */.
Examples:
/* Copyright 2009 Gnomovision, Inc. */ univ: u99999 // Don't panic!