1 / 39

Implementing Constraints

Implementing Constraints. Overview. A look at the literature CSPs Arc consistency algorithms Implementation in ECLiPSe: Low level: Suspensions and Attributes Prototyping in ECLiPSe: Intermediate: Constraint Handling Rules (CHR) High level: Propia. Constraint Satisfaction Problems (CSP).

favian
Download Presentation

Implementing Constraints

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Implementing Constraints

  2. Overview • A look at the literature • CSPs • Arc consistency algorithms • Implementation in ECLiPSe: • Low level: Suspensions and Attributes • Prototyping in ECLiPSe: • Intermediate: Constraint Handling Rules (CHR) • High level: Propia

  3. Constraint Satisfaction Problems (CSP) • Much of the literature talks about “CSPs” • This usually refers to binary CSPs: • A fixed set of variables X1,…Xn • Every variable has a finite domain Di • arbitrary domain, does not have to be ordered • Binary (2-variable) constraints only cij(Xi,Xj) • constraint defined as sets of consistent value pairs • Any CSP can be transformed to binary CSP • We don’t normally do that • Instead generalise binary techniques

  4. Static properties of a CSP network • Node consistency • vDi: ci(v) • Not very interesting • Arc consistency • vDi wDj : cij(v,w) • Most relevant • Path consistency • vDi wDj uDk: cik(v,u),ckj(u,w) • Usually too expensive       …    

  5. Arc consistency algorithms • Consistency in networks of relations [AC1-3] • A.K. Mackworth, in Artificial Intelligence 8, pages 99-118, 1977. • Arc and path consistency revised [AC4] • R. Mohr and T.C. Henderson, in Artificial Intelligence 28, pages 225-233, 1986. • A generic arc-consistency algorithm and its specializations [AC5] • P. Van Hentenryck, Y. Deville, and C.-M. Teng, in Artificial Intelligence 57, pages 291-321, 1992. • Arc-consistency and arc-consistency again [AC6] • C. Bessiere, in Artificial Intelligence 65, pages 179-190, 1994. • Using constraint metaknowledge to reduce arc consistency computation [AC7] • C. Bessiere, E.C. Freuder, and J.-R. Régin, in Artificial Intelligence 107, pages 125-148, 1999.

  6. AC-1 • procedure REVISE(Vi,Vj) • DELETE <- false; • for each X in Di do • if there is no such Y in Dj such that (X,Y) is consistent, • then • delete X from Di; • DELETE <- true; • endif; • endfor; • return DELETE; • procedure AC-1 • end REVISE • Q <- {(Vi,Vj) in arcs(G),i#j}; • repeat • CHANGE <- false; • for each (Vi,Vj) in Q do • CHANGE <- REVISE(Vi,Vj) or CHANGE; • endfor • until not(CHANGE) • end AC-1 • G is the constraint graph, Q is a queue

  7. AC-3 • procedure AC-3 • Q <- {(Vi,Vj) in arcs(G),i#j}; • while not Q empty • select and delete any arc (Vk,Vm) from Q; • if REVISE(Vk,Vm) then • Q <- Q union {(Vi,Vk) such that • (Vi,Vk) in arcs(G),i#k,i#m} • endif • endwhile • end AC-3 • Re-check only arcs that were affected • Queue contains arcs (constraints) • This is a practical algorithm • Easy to generalise to n-ary constraints

  8. AC-4 - initialization • procedure INITIALIZE • Q <- {}; • S <- {}; % initialize each element of structure S • for each (Vi,Vj) in arcs(G) do % (Vi,Vj) and (Vj,Vi) are same elements • for each a in Di do • total <- 0; • for each b in Dj do • if (a,b) is consistent according to the constraint (Vi,Vj) then • total <- total+1; • Sj,b <- Sj,b union {<i,a>}; • endif • endfor; • counter[(i,j),a] <- total; • if counter[(i,j),a]=0 then • delete a from Di; • Q <- Q union {<i,a>}; • endif; • endfor; • endfor; • return Q; • end INITIALIZE

  9. AC-4 - fixpoint computation • procedure AC-4 • Q <- INITIALIZE; • while not Q empty • select and delete any pair <j,b> from Q; • counter[(i,j),a] <- counter[(i,j),a] - 1; • for each <i,a> from Sj,b do • if counter[(i,j),a]=0 & a is still in Di then • delete a from Di; • Q <- Q union {<i,a>}; • endif • endfor • endwhile • end AC-4 • Maintains support counters for each domain element • Queue contains information about the deleted domain value

  10. Relation to Search • These algorithms look at the constraint network statically • They are not strong enough to enforce global consistency of the network, so we still need search • Search decisions change some domain(s), which means we may lose any achieved xxx-consistency • Overall design needs to answer 2 questions: • What level(s) of consistency do we want to employ? • At what time (during search) do we want which consistency?

  11. Consistency during search • Generate and test • Instantiate all problem variables, then check all constraints • Standard backtracking • Check every constraint as soon as both its variables are instantiated • Forward Checking (~ Label Propagation) • Look ahead • When one variable is instantiated make the constraint arc consistent • When a variable is instantiated, make the whole graph arc consistent again (maintain arc consistency at all times) (This terminology used in P.v.Hentenryck: Constraint Satisfaction in LP)

  12. Other forms of consistency • Interval (bounds) consistency • Useful for ordered domains • We don’t look at every domain value • Only make sure that smallest and largest domain value are consistent • Depending on the constraint semantics, bounds consistency implies arc consistency, or not • Used in many ECLiPSe libraries • lib(fd) - integer domain • lib(ic) - integer and real number domain • lib(ic_sets) - integer set domain • lib(ic_symbolic) - ordered symbolic domain • …

  13. Implementing Constraints with Suspensions and Atrributes

  14. What you need to know To implement additional constraint for existing solver: • suspend / resume mechanism • the solver’s domain access interface To implement a solver over a new domain: • variable attribute mechanism

  15. Basic Programming Support • Suspending the execution of goals • delay-clause or suspend/3,4 •  Corresponds to the queue in AC-3! • Data/Event-driven waking on change • attaching to variables + condition • Change notifications • Allows to say when computation should happen • messages from variables to constraints (see lib(notify_ports)) • Information about what changed (for AC-4 style algorithms) • Priorities for goals •  Allows to tune efficiency

  16. suspend (delay) Delayed Goals s2 s3 s1 r1, …, rk, q1, …, qm, sl s4 Prio 1 Prio 2 … Prio 12 schedule (wake) Resolvent in ECLiPSe p1 , … , pn .

  17. Consistency check capacity(T,N) :- (var(T);var(N)), !, suspend(capacity(T,N), 0, [T,N]->inst). capacity(1, N) :- N>=0.0, N=<350.0. capacity(2, N) :- N>=0.0, N=<180.0. capacity(3, N) :- N>=0.0, N=<50.0. Declarative style capacity(1, N) :- N>=0.0, N=<350.0. capacity(2, N) :- N>=0.0, N=<180.0. capacity(3, N) :- N>=0.0, N=<50.0. delay capacity(T,N) if var(T);var(N). Imperative style

  18. Forward Checking :- lib(ic). delay capacity(Type,N) if var(Type),var(N). capacity(Type, N) :- var(N), ( Type=1 -> N :: 0.0..350.0 ; Type=2 -> N :: 0.0..180.0 ; Type=3 -> N :: 0.0..50.0 ; fail ). capacity(Type, N) :- nonvar(N), N>=0.0, ( N=<50.0 -> Type :: [1,2,3] ; N=<180.0 -> Type :: [1,2] ; N=<350.0 -> Type = 1 ; fail ).

  19. c_fwd X Y c_bwd Constraint via Propagation Goals Alternatively implemented as X Y c X Y c_prop

  20. Forward Checking - 2 agents capacity(Type, N) :- capacity_forward(Type, N), capacity_backward(Type, N). delay capacity_forward(Type, _N) if var(Type). capacity_forward(Type, N) :- ( Type=1 -> N :: 0.0..350.0 ; Type=2 -> N :: 0.0..180.0 ; Type=3 -> N :: 0.0..50.0 ; fail ). delay capacity_backward(_Type, N) if var(N). capacity_backward(Type, N) :- N>=0.0, ( N=<50.0 -> Type :: [1,2,3] ; N=<180.0 -> Type :: [1,2] ; N=<350.0 -> Type = 1 ; fail ).

  21. Explicitly Suspending Goals Providing more flexibility than delay-clauses • Creation • make_suspension(+Goal, +Priority, -Suspension) • Attaching to attributed variable • insert_suspension(+Vars, +Suspension, +Index, +AttributeName) • Combined create & attach • suspend(+Goal, +Priority, +Condition) • suspend(+Goal, +Priority, +Condition, -Suspension) • Delayed goal viewer shows suspended goals

  22. Triggering of suspensions When goals (constraints) are suspended, they are usually attached to variables with trigger conditions: • X->inst • when X becomes instantiated (most specific) • X->constrained • when X becomes constrained in any way (most general) • X->ic:min, X->ic:max, X->ic:hole, X->type • when the lower bound / upper bound / other value in the domain of X changes • Other trigger conditions are defined by the various solvers

  23. Bounds consistency Bounds-consistent greater-equal: ge(X, Y) :- get_max(X, XH), % get current bounds get_min(Y, YL), impose_min(X, YL), % impose new bounds impose_max(Y, XH). X >= Y ( var(X),var(Y) -> suspend(ge(X,Y), 0, [[X,Y]->constrained]) ; true ),

  24. More precise waking conditions Bounds-consistent greater-equal: ge(X, Y) :- ( var(X),var(Y) -> suspend(ge(X,Y), 0, [X->ic:max,Y->ic:min]) ; true ), get_max(X, XH), get_min(Y, YL), impose_min(X, YL), impose_max(Y, XH). X >= Y

  25. Variables, Attributes and Suspended Goals X { suspend: inst constrained ic: 1..9 min max hole } Y { suspend: inst constrained ic: 1..9 min max hole } ge(X,Y)

  26. Directional propagators ge(X, Y) :- ge_fwd(X,Y), ge_bwd(X,Y). ge_fwd(X, Y) :- ( var(X) -> suspend(ge_fwd(X,Y), 0, [X->ic:max]) ; true ), get_max(X, XH), impose_max(Y, XH). ge_bwd(X, Y) :- ( var(Y) -> suspend(ge_bwd(X,Y), 0, [Y->ic:min]) ; true ), get_min(Y, YL), impose_min(X, YL). X >= Y

  27. Directional Propagators X { suspend: inst constrained ic: 1..9 min max hole } Y { suspend: inst constrained ic: 1..9 min max hole } ge_fwd(X,Y) ge_bwd(X,Y)

  28. Repeated waking on domain updates • E.g. propagating bounds • ge(X, Y) :- • ( var(X),var(Y) -> • suspend(ge(X,Y), 0, [X->ic:max, Y->ic:min]) • ; true ), • get_max(X, XH), • get_min(Y, YL), • impose_min(X, YL), % impose new bounds • impose_max(Y, XH). • Properties • variables remain variables • arbitrary number of steps (limited only by domain size) • Potential performance problem: • re-suspending identical goal over and over again! X >= Y

  29. Domain/bounds propagation using a “demon” • Same constraint as before: • ge(X, Y) :- • suspend(ge(X,Y,Susp), 0, [X->ic:max, Y->ic:min], Susp), ge(X, Y, Susp). • :- demon ge/3. % demon declaration • ge(X, Y, Susp) :- • ( var(X),var(Y) -> true % implicitly re-suspend • ; kill_suspension(Susp) ), % explicit kill • get_max(X, XH), • get_min(Y, YL), • impose_min(X, YL), % impose new bounds • impose_max(Y, XH). • A “demon” does not need to be re-suspended When woken, it splits into a woken and a suspended instance Needs to be killed explicitly when no longer needed

  30. Variables, Attributes and Suspended Demon X { suspend: inst constrained ic: 1..9 min max hole } Y { suspend: inst constrained ic: 1..9 min max hole } ge(X,Y,Susp)

  31. Single-propagator max-constraint mymax(A, B, M):- get_bounds(A, MinA, MaxA), get_bounds(B, MinB, MaxB), get_bounds(M, MinM, MaxM), ( MinA >= MaxB -> A = M ; MinB >= MaxA -> B = M ; MinM > MaxB -> A = M ; MinM > MaxA -> B = M ; call_priority(( Max is max(MaxA, MaxB), Min is max(MinA, MinB), impose_bounds(M, Min, Max), impose_max(A, MaxM), impose_max(B, MaxM), Vars = [A,B,M], ( nonground(2, Vars, _) -> suspend(mymax(A, B, M), 3, [Vars->ic:max,Vars->ic:min]) ; true ) ), 2) ).

  32. N-ary constraints Even more implementation choices: • Level of consistency • Algorithm • Eagerness • Trigger conditions and priority • Logical decomposition • e.g. alldifferent  many disequality constraints • Operational decomposition • One or several propagator goals • Data-driven vs explicit fixpoint computation

  33. Special case: Incremental checking (1) • Value X occurs in List : • among(X, [Y|Ys]) :- • ( var(Y) -> • suspend(among(X, [Y|Ys]),0,Y->inst) • ; X = Y -> • true • ; • among(X, Ys) • ). • Properties • efficient, looks at most once at each list element • delayed goal may be different after each step • success after 1..N steps or failure after N steps

  34. Incremental checking (2) • Value X does not occur in List: • not_among(X, []). • not_among(X, [Y|Ys]) :- • ( var(Y) -> • suspend(not_among(X, [Y|Ys]),0,Y->inst) • ; • X \= Y, • not_among(X, Ys) • ). • Properties • Success after N steps or failure after 1..N steps • But: there may be an X at the end of the list, behind a variable! • Failure can be detected unnecessarily late

  35. Parallel checking • Value X does not occur in List: • not_among(X, []). • not_among(X, [Y|Ys]) :- • ( var(Y) -> • suspend(X\=Y, 0, Y->inst) • ; • X \= Y • ), • not_among(X, Ys). • Properties • Can expand into up to N delayed goals X\=Y • Failure detected as soon as possible • Normally more interesting than detecting success!

  36. Implementing a new domain :- module(enum). % library name :- meta_attribute(enum, [ % attribute name and handlers unify: unify_enum/2, print: print_enum/2, compare_instances: ..., copy_term: ...]). make_enum_variable(Var, Values) :- % constructor Attr = enum(Values,_), init_suspension_list(2, Attr), add_attribute(Var, Attr). unify_enum(Value, Attribute) :- % unify handler check if Value is compatible with Attribute exclude(Var{Attribute}, Value) ?- % domain access primitive delete Value from possible values in Attribute ...

  37. Exercise 1 • Write a constraint atmost(+N, +List, +Value) • Meaning: at most N elements of List have value Value • Behaviour: fail as soon as more than N elements are instantiated to Value • Improvement: fail as soon as not enough variables with Value in their domain are left over

  38. Exercise 2 • Write a constraint • offset(?X,+C,?Y) • which is like • offset(X,C,Y) :- Y #= X+C. • But maintains domain consistency (propagates “holes”) • Use • Suspension built-ins • Domain access primitives from the ic_kernel module

  39. Domain attribute access in lib(ic) • Getting domain representation from a variable • get_domain_as_list(+Var, -ListOfValues) • get_bounds(+Var, -Min, -Max) • get_min(+Var, -Min) • get_max(+Var, -Max) • get_domain_size(+Var, -Size) • ... • Updating a variable’s domain • impose_bounds(+Var, +Min, +Max) • impose_min(+Var, +Min) • impose_max(+Var, +Max) • exclude(+Var, +Value) • ...

More Related