CSP-to-CSP Translation by Sugar
Table of Contents
- What's New
- Introduction
- Download
- Usage
- Translations
- Optional translations
- max (default off)
- weighted (default off)
- peephole, peep (default on)
- linearize, linear (default on)
- propagation, prop (default on)
- normalize_linearsum, norm (default on)
- simplify_clauses, simp (default on)
- reduce_arity, reduce (default on)
- decompose, decomp (default on)
- replace_arguments, replace_args (default off)
- hints (default on)
- Output
- Example
- Writing Prolog program to generate customized output
- Translation Hooks
- Output Hooks
What's New
- First public release
Introduction
This document explains the usage of CSP-to-CSP translation function of Sugar.
Download
- trans.zip (sample input and output files, and trans.pro program)
Usage
Java command
java -jar sugar-v2-1-2.jar -option options -to csp output.csp input.csp
- The above command generates the output in Sugar CSP format.
- By replacing
-to csp
option with-to prolog
, Prolog format output is generated. - The options string is a list of option settings separated by commas (,). Option setting is either an option name or an option name preceded with "no_".
Example
$ java -jar sugar-v2-1-2.jar -option no_norm,no_simp,no_reduce,no_decomp,no_hints -to csp output.csp input.csp
Sugar command
The next command can be used to get the same result.
sugar -option options -translate format -output output.csp input.csp
- The format is either
csp
orprolog
.
Example
$ sugar -option no_norm,no_simp,no_reduce,no_decomp,no_hints -translate csp -output output.csp input.csp
Translations
The following translations are always performed.
- Domain names are replaced with their definitions.
For example,(domain d0 1 9) (int x d0)
is converted to the following.
(int x ((1 9)))
- Predicates are expanded with their definitions.
For example,(predicate (p0 x1 x2) (<= x1 (+ x2 1))) (p0 (+ x 1) 2)
is converted to the following at first, and further translations are performed.
(<= (+ x 1) (+ 2 1))
- Each constraint is converted to clausal form when
linearize
option is set. Each clause consists of the followings or their nagations.- Boolean variable
- Relation
- Linear comparison (eq, ne, le)
- General comparison (when it is not linearized)
- Global constraint (when it is not decomposed)
Optional translations
max (default off)
This option performs MaxCSP-to-CSP translation.
weighted (default off)
This option performs WeightedCSP-to-CSP translation.
peephole, peep (default on)
This option performs peephole optimization for some expressions, such as x ⋅ y ≤ 0 and abs(x) ≤ y.
linearize, linear (default on)
This option enables the translation to linear constraints.
propagation, prop (default on)
This option performs constraint propagation to reduce domains of integer variables and remove redundant constraints.
normalize_linearsum, norm (default on)
This option performs conversion of linear comparisons (eq, ne, le, lt, ge, gt) to linear comparisons of "le" or "ge". When this option is disabled and linearize option is set, linear comparisons are converted to "eq", "ne", "le", or "ge".
simplify_clauses, simp (default on)
This option performs Tseitin translation so that each clause contains at most one non-simple literal. The followings are simple literals.
- Boolean variable or its negation
- Linear comparison x≤ a or x≥ a
reduce_arity, reduce (default on)
This option reduces the arity of linear comparisons by introducing new integer variables.
- When "arity=n" is specified, "n" is used as the maximum arity.
decompose, decomp (default on)
This option performs decomposition of all global constraints. The option for each global constraint is as follows.
- decompose_alldifferent, decomp_alldiff
- decompose_weightedsum, decomp_wsum
- decompose_cumulative, decomp_cumul
- decompose_element, decomp_elem
- decompose_disjunctive, decomp_disj
- decompose_lex_less, decomp_lex_less
- decompose_lex_lesseq, decomp_lex_lesseq
- decompose_nvalue, decomp_nvalue
- decompose_global_cardinality, decomp_gc
- decompose_global_cardinality_with_costs, decomp_gcc
- decompose_count, decomp_count
replace_arguments, replace_args (default off)
This option replaces the expressions used as the arguments of alldifferent constraints to integer variables.
hints (default on)
This option adds pigeon-hole clauses (Hall clauses) to alldifferent constraints.
Output
CSP output
The following explains the format of the output
under linear
, prop
, no_norm
, no_simp
, no_reduce
, no_decomp
, no_hints
settings.
Only the differences from the original Sugar syntax are described.
Integer Variable Definitions
IntegerVariableDefinition ::= (int IntegerVariableName (Range+)) Range ::= (Integer Integer)
Boolean Variable Definitions
BooleanVariableDefinition ::= (bool BooleanVariableName)
- This is same with the original syntax definition.
Relation Definitions
RelationDefinition ::= (relation RelationName Arity RelationBody)
- This is same with the original syntax definition.
Predicate Definitions
- No predicate definitions are included in the output.
Constraints
Constraint ::= Clause Clause ::= Literal | (or Literal+) Literal ::= BooleanVariableName | (not BooleanVariableName) | (RelationName Term*) | (not (RelationName Term*)) | LinearComparison | GlobalConstraint | (not GlobalConstraint) LinearCompariosn ::= (wsum (WeightedPair*) Comparison Integer) WeightedPair ::= (Integer IntegerVariableName) Comparison ::= eq | ne | le GobalConstraint ::= AllDifferentConstraint | WeightedSumConstraint | CumulativeConstraint | ElementConstraint | DisjunctiveConstraint | Lex_lessConstraint | Lex_lesseqConstraint | NvalueConstraint | Global_cardinalityConstraint | Global_cardinality_with_costsConstraint | CountConstraint
- When translated from XCSP input, the arguments of relations are only integer variables or integer constants.
- When translated from XCSP input, the arguments of global constraints are only integer variables or integer constants.
- When
normalize_linearsum
option is specified, Comparison is alwaysle
.
CSP
CSP ::= false | IntegerVariableDefinition* BooleanVariableDefinition* RelationDefinition* ObjectiveDeclaration? Constraint*
Prolog output
It is isomorphic to CSP output.
Example
The following example.csp file is used.
(int x 1 9) (int y (2 3 5 8 9)) (int z ((1 3) 5 (7 9))) (int w -1000 1000) (bool p) (bool q) (bool r) (relation r 2 (conflicts (1 2) (3 4))) (imp p (imp q r)) (iff (r x y) (r y x)) (> (+ x y) 10) (imp (= x 9) (and p q (= z 1))) (or (>= (+ x y) 10) (>= (+ y z) 10)) (>= (+ w (abs w) x y z) 100) (alldifferent x y z)
CSP to CSP
Options | linear | prop | norm | simp | reduce | decomp | hints |
---|---|---|---|---|---|---|---|
example-xxxxxxx.csp | - | - | - | - | - | - | - |
example-Lxxxxxx.csp | Y | - | - | - | - | - | - |
example-LPxxxxx.csp | Y | Y | - | - | - | - | - |
example-LPNxxxx.csp | Y | Y | Y | - | - | - | - |
example-LPNSxxx.csp | Y | Y | Y | Y | - | - | - |
example-LPNSRxx.csp | Y | Y | Y | Y | Y | - | - |
example-LPNSRDx.csp | Y | Y | Y | Y | Y | Y | - |
example-LPNSRDH.csp | Y | Y | Y | Y | Y | Y | Y |
- The generated CSP files can be used as Sugar input files.
CSP to Prolog
Options | linear | prop | norm | simp | reduce | decomp | hints |
---|---|---|---|---|---|---|---|
example-xxxxxxx.pro | - | - | - | - | - | - | - |
example-Lxxxxxx.pro | Y | - | - | - | - | - | - |
example-LPxxxxx.pro | Y | Y | - | - | - | - | - |
example-LPNxxxx.pro | Y | Y | Y | - | - | - | - |
example-LPNSxxx.pro | Y | Y | Y | Y | - | - | - |
example-LPNSRxx.pro | Y | Y | Y | Y | Y | - | - |
example-LPNSRDx.pro | Y | Y | Y | Y | Y | Y | - |
example-LPNSRDH.pro | Y | Y | Y | Y | Y | Y | Y |
Writing Prolog program to generate customized output
It seems a good approach to write a Prolog program which reads Prolog list format output and generates desired output.
trans.pro is such a small Prolog program runnable under SWI-Prolog. trans.sh is a shell script to run the program.
$ ./trans.sh example-LPxxxxx.pro
The following is an output of trans.pro program for example-LPxxxxx.pro.
int(x,'.'(range(2,9),[])). int(y,'.'(range(2,3),'.'(range(5,5),'.'(range(8,9),[])))). int(z,'.'(range(1,3),'.'(range(5,5),'.'(range(7,9),[])))). int(w,'.'(range(-927,1000),[])). int('$I1','.'(range(0,1000),[])). bool(p). bool(q). bool(r). bool('$B1'). relation(r,2,conflicts,'.'('.'(1,'.'(2,[])),'.'('.'(3,'.'(4,[])),[]))). constraint(1). constraint_elem(1,not(p)). constraint_elem(1,not(q)). constraint_elem(1,r). constraint(2). constraint_elem(2,not(rel(r,'.'(x,'.'(y,[]))))). constraint_elem(2,rel(r,'.'(y,'.'(x,[])))). constraint(3). constraint_elem(3,rel(r,'.'(x,'.'(y,[])))). constraint_elem(3,not(rel(r,'.'(y,'.'(x,[]))))). constraint(4). constraint_elem(4,rel(wsum,'.'('.'('.'(1,'.'(x,[])),'.'('.'(1,'.'(y,[])),[])),'.'(ge,'.'(11,[]))))). constraint(5). constraint_elem(5,rel(wsum,'.'('.'('.'(1,'.'(x,[])),[]),'.'(ne,'.'(9,[]))))). constraint_elem(5,'$B1'). constraint(6). constraint_elem(6,p). constraint_elem(6,not('$B1')). constraint(7). constraint_elem(7,q). constraint_elem(7,not('$B1')). constraint(8). constraint_elem(8,rel(wsum,'.'('.'('.'(1,'.'(z,[])),[]),'.'(eq,'.'(1,[]))))). constraint_elem(8,not('$B1')). constraint(9). constraint_elem(9,rel(wsum,'.'('.'('.'(1,'.'(x,[])),'.'('.'(1,'.'(y,[])),[])),'.'(ge,'.'(10,[]))))). constraint_elem(9,rel(wsum,'.'('.'('.'(1,'.'(y,[])),'.'('.'(1,'.'(z,[])),[])),'.'(ge,'.'(10,[]))))). constraint(10). constraint_elem(10,rel(wsum,'.'('.'('.'(1,'.'('$I1',[])),'.'('.'(-1,'.'(w,[])),[])),'.'(ge,'.'(0,[]))))). constraint(11). constraint_elem(11,rel(wsum,'.'('.'('.'(1,'.'('$I1',[])),'.'('.'(1,'.'(w,[])),[])),'.'(ge,'.'(0,[]))))). constraint(12). constraint_elem(12,wsum('.'(mul(1,'$I1'),'.'(mul(-1,w),[])),le,0)). constraint_elem(12,wsum('.'(mul(1,'$I1'),'.'(mul(1,w),[])),le,0)). constraint(13). constraint_elem(13,rel(wsum,'.'('.'('.'(1,'.'('$I1',[])),'.'('.'(1,'.'(w,[])),'.'('.'(1,'.'(x,[])),'.'('.'(1,'.'(y,[])),'.'('.'(1,'.'(z,[])),[]))))),'.'(ge,'.'(100,[]))))). constraint(14). constraint_elem(14,alldifferent('.'(x,'.'(y,'.'(z,[]))))).
- List
[x1,x2,...,xn]
is represented by a nested term '.'(x1, '.'(x2, …, '.'(xn, []) …)).
Translation Hooks
You can add hooks of calling your conversion program to the translation procedure.
Solving CSP with your conversion program
- Write your conversion program implementing
jp.kobe_u.sugar.hook.ConverterHook
interface. See ExampleHook.java as an example program. - Compile
$ javac -cp sugar-v2-1-2.jar ExampleHook.java
- Run
$ sugar -jar .:sugar-v2-1-2.jar -conversionHooks ExampleHook example2.csp
Translating CSP with your conversion program
- Write your conversion program implementing
jp.kobe_u.sugar.hook.ConverterHook
interface. See ExampleHook.java as an example program. - Compile
$ javac -cp sugar-v2-1-2.jar ExampleHook.java
- Run
$ java -cp .:sugar-v2-1-2.jar jp.kobe_u.sugar.SugarMain -conversionHooks ExampleHook -option no_norm,no_simp,decomp -to csp example2out.csp example2.csp
Alternatively way
$ sugar -jar .:sugar-v2-1-2.jar -conversionHooks ExampleHook -option no_norm,no_simp,decomp -translate csp -output example2out.csp example2.csp
Example input
(int x1 0 99) (int x2 0 99) (int x3 0 99) (int y1 1 3) (int y2 1 3) (int y3 1 3) (= x1 myconstant) (mypredicate x1 x2 x3) (alldifferent y1 y2 y3)
Example output
; File generated by sugar.Output (int x1 ((55 55))) (int x2 ((56 98))) (int x3 ((57 99))) (int y1 ((1 3))) (int y2 ((1 3))) (int y3 ((1 3))) ; (eq x1 myconstant) (wsum ((1 x1)) eq 55) ; (mypredicate x1 x2 x3) (wsum ((1 x1) (-1 x2)) le -1) (wsum ((1 x2) (-1 x3)) le -1) ; (alldifferent y1 y2 y3) (or (wsum ((1 y1)) ge 3) (wsum ((1 y2)) ge 3) (wsum ((1 y3)) ge 3)) (or (wsum ((1 y1)) le 1) (wsum ((1 y2)) le 1) (wsum ((1 y3)) le 1)) (or (wsum ((1 y1)) eq 1) (wsum ((1 y2)) eq 1) (wsum ((1 y3)) eq 1)) (or (wsum ((1 y1)) eq 2) (wsum ((1 y2)) eq 2) (wsum ((1 y3)) eq 2)) (or (wsum ((1 y1)) eq 3) (wsum ((1 y2)) eq 3) (wsum ((1 y3)) eq 3))
Example program
import java.util.ArrayList; import java.util.List; import jp.kobe_u.sugar.SugarException; import jp.kobe_u.sugar.converter.Converter; import jp.kobe_u.sugar.csp.Clause; import jp.kobe_u.sugar.csp.IntegerDomain; import jp.kobe_u.sugar.expression.Expression; import jp.kobe_u.sugar.expression.Sequence; import jp.kobe_u.sugar.hook.ConverterHook; /** * @author Naoyuki Tamura (tamura@kobe-u.ac.jp) * */ public class ExampleHook implements ConverterHook { private static Expression MyConstant = Expression.create("myconstant"); private static Expression MyPredicate = Expression.create("mypredicate"); @Override public Expression convertFunction(Converter converter, Expression x) throws SugarException { if (x.equals(MyConstant)) { // myconstant --> 55 Expression z = Expression.create(55); return z; } return x; } @Override public Expression convertConstraint(Converter converter, Expression x, boolean negative, List<Clause> clauses) throws SugarException { if (x.isSequence(MyPredicate)) { // (mypredicate x1 x2 x3 ...) --> (and (< x1 x2) (< x2 x3) ...) Sequence seq = (Sequence) x; List<Expression> xs = new ArrayList<Expression>(); xs.add(Expression.AND); for (int i = 1; i < seq.length() - 1; i++) xs.add(seq.get(i).lt(seq.get(i + 1))); Expression z = Expression.create(xs); return z; } else if (x.isSequence(Expression.ALLDIFFERENT)) { return convertAlldifferent(converter, (Sequence)x, negative, clauses); } return x; } private Expression convertAlldifferent(Converter converter, Sequence seq, boolean negative, List<Clause> clauses) throws SugarException { // Convert alldifferent by default Expression z = converter.convertGlobal(seq, negative, clauses); // Get arguments Expression[] args; if (seq.length() == 2 && seq.get(1).isSequence()) { args = ((Sequence) seq.get(1)).getExpressions(); } else { args = new Expression[seq.length() - 1]; for (int i = 1; i < seq.length(); i++) args[i - 1] = seq.get(i); } int n = args.length; // Calculate bounds of the arguments int lb = Integer.MAX_VALUE; int ub = Integer.MIN_VALUE; for (Expression x : args) { IntegerDomain d = converter.convertFormula(x).getDomain(); lb = Math.min(lb, d.getLowerBound()); ub = Math.max(ub, d.getUpperBound()); } // Add At-Least-One clause when it is a permutation if (n == ub - lb + 1) { for (int value = lb; value <= ub; value++) { List<Expression> alo = new ArrayList<Expression>(); alo.add(Expression.OR); for (Expression x : args) { alo.add(x.eq(value)); } if (z == null) z = Expression.create(alo); else z = z.and(Expression.create(alo)); } } return z; } }
Output Hooks
You can add hook of calling your output program.
Ouptut with your conversion program
- Write your output program implementing
jp.kobe_u.sugar.OutputInterface
interface. - Compile
$ javac -cp sugar-v2-1-2.jar Output.java
- Run
$ java -cp .:sugar-v2-1-2.jar jp.kobe_u.sugar.SugarMain -outputHook Output -option no_norm,no_simp,decomp -to csp example2out.csp example2.csp
Alternatively way
$ sugar -jar .:sugar-v2-1-2.jar -outputHook Output -option no_norm,no_simp,decomp -translate csp -output example2out.csp example2.csp