:- module(tentative_constraints).
:- export alldifferent_t / 3.
:- export alldifferent_t / 2.
:- export integral_t / 3.
:- export eq_t / 3.
:- export neq_t / 3.
:- reexport tentative.
:- export op(700, xfx, $=).
:- export op(700, xfx, $\=).
:- comment(summary, "Tentative value implementations for some basic constraints").
:- comment(author, "Joachim Schimpf").
:- comment(date, "$Date: 2006/09/23 01:54:01 $").
:- comment(copyright, "Cisco Systems").
:- comment(desc, html("\n    This library contains tentative value implementations for some basic\n    constraints.  It is intended to be used together with lib(tentative),\n    which provides the underlying primitives and facilities to create\n    tentative variables, manage constraint sets, and to do search.\n")).
:- comment(see_also, [library(tentative)]).
:- comment(eg, "\n    %\n    % The following code implements a solution to the N-queens problem,\n    % using a steepest-ascent hill-climbing heuristic.\n    %\n\n    :- lib(tentative).\n    :- lib(tentative_constraints).\n\n    queens(N, Board) :-\n\t    dim(Board, [N]),\t\t\t% make variables\n\t    tent_set_random(Board, 1..N),\t% init tentative values\n\n\t    dim(Pos, [N]),\t\t\t% aux arrays of constants\n\t    ( foreacharg(I,Pos), for(I,0,N-1) do true ),\n\t    dim(Neg, [N]),\n\t    ( foreacharg(I,Neg), for(I,0,-N+1,-1) do true ),\n\n\t    CS :~ alldifferent(Board),\t\t% setup constraints ...\n\t    CS :~ alldifferent(Board, Pos),\t% ... in conflict set CS\n\t    CS :~ alldifferent(Board, Neg),\n\n\t    cs_violations(CS, TotalViolation),\t% search part\n\t    steepest(Board, N, TotalViolation),\n\n\t    tent_fix(Board),\t\t\t% instantiate variables\n\t    cs_clear_satisfied(CS).\t\t% clean up conflict set\n\n\n    steepest(Board, N, Violations) :-\n\t    vs_create(Board, Vars),\t\t% create variable set\n\t    Violations tent_get V0,\t\t% initial violations\n\t    SampleSize is fix(sqrt(N)),\t\t% neighbourhood size\n\t    (\n\t\tfromto(V0,_V1,V2,0),\t\t% until no violations left\n\t\tparam(Vars,N,SampleSize,Violations)\n\t    do\n\t\tvs_worst(Vars, X),\t\t% get a most violated variable\n\t\ttent_minimize_random(\t\t% find a best neighbour\n\t\t    (\t\t\t\t% nondeterministic move\n\t\t\trandom_sample(1..N,SampleSize,I),\n\t\t\tX tent_set I\n\t\t    ),\n\t\t    Violations,\t\t\t% violation variable\n\t\t    I\t\t\t\t% best move-id\n\t\t),\n\t\tX tent_set I,\t\t\t% do the move\n\t\tViolations tent_get V2\t\t% new violations\n\t    ).\n").
:- comment(alldifferent_t / 2, [summary : "Tentative value implementation of alldifferent constraint", amode : (alldifferent_t(+, +) is det), args : ["Cs" : "A list or array of variables/values", "MC" : "A monitored_constraint descriptor"], see_also : [alldifferent_t / 3, neq_t / 3, tent_implements / 2], desc : html("\n    \tTentative value implementation of alldifferent constraint.\n\t<P>\n\tThe violatedness of the constraint is the number of identical\n\tvalue pairs among its arguments.\n\t<P>\n\tThe following declaration is in effect, meaning that alldifferent_t/2\n\tis used whenever alldifferent/1 is added to a constraint set:\n\t<PRE>\n\t:- alldifferent_t/2 tent_implements alldiffernet/1.\n\t</PRE>\n    "), eg : "\n    ?- Xs = [A,B,C], Xs tent_set [1,2,3], CS :~ alldifferent(Xs).\n    Xs = [A{1 -> 0}, B{2 -> 0}, C{3 -> 0}]\n    CS = constraint_set(TotalVio{0 -> 0}, ...)\n    There is 1 delayed goal.\n    Yes (0.00s cpu)\n    "]).
:- comment(alldifferent_t / 3, [summary : "Tentative value implementation of alldifferent/2 constraint", amode : (alldifferent_t(+, +, +) is det), args : ["Xs" : "A list or array of variables/values", "Cs" : "A list or array of numbers", "MC" : "A monitored_constraint descriptor"], see_also : [alldifferent_t / 2, neq_t / 3, tent_implements / 2], desc : html("\n    \tTentative value implementation of alldifferent constraint with\n\toffsets. The difference releationship must hold between the\n\tvalues resulting from adding each variable Xi to its corresponding\n\toffset Ci.\n\t<P>\n\tThe violatedness of the constraint is the number of identical\n\tvalue pairs among these Xi+Ci values.\n\t<P>\n\tThe following declaration is in effect, meaning that alldifferent_t/3\n\tis used whenever alldifferent/2 is added to a constraint set:\n\t<PRE>\n\t:- alldifferent_t/3 tent_implements alldiffernet/2.\n\t</PRE>\n    "), eg : "\n    ?- Xs = [A,B,C], Xs tent_set [1,2,3], CS :~ alldifferent(Xs, [1,0,0]).\n    Xs = [A{1 -> 1}, B{2 -> 1}, C{3 -> 0}]\n    CS = constraint_set(TotalVio{1 -> 0}, ...)\n    There is 1 delayed goal.\n    Yes (0.00s cpu)\n    "]).
:- comment(eq_t / 3, [summary : "Tentative value implementation of $=/2 arithmetic equality constraint", amode : (eq_t(?, ?, +) is det), args : ["X" : "Expression containing tentative variables", "Y" : "Expression containing tentative variables", "MC" : "A monitored_constraint descriptor"], see_also : [alldifferent_t / 2, alldifferent_t / 3, neq_t / 3, tent_implements / 2], desc : html("\n\t<P>\n    \tTentative value implementation of equality constraint.\n\t</P><P>\n\tThe violatedness of the constraint is 0 if the equality holds,\n\t1 otherwise.\n\t</P><P>\n\tThe following declaration is in effect, meaning that eq_t/3\n\tis used whenever $= /2 is added to a constraint set:\n\t<PRE>\n\t:- eq_t/3 tent_implements $= /2.\n\t</PRE>\n\t</P>\n    "), eg : "\n    ?- [X, Y] tent_set [3, 4], CS :~ (X $= Y).\n    X = X{3 -> 0}\n    Y = Y{4 -> 0}\n    CS = constraint_set(TotalVio{1 -> 0}, ...)\n    There is 1 delayed goal.\n    Yes (0.00s cpu)\n\n    ?- [X, Y] tent_set [3, 3], CS :~ (X $= Y).\n    X = X{3 -> 0}\n    Y = Y{3 -> 0}\n    CS = constraint_set(TotalVio{0 -> 0}, ...)\n    There is 1 delayed goal.\n    Yes (0.00s cpu)\n    "]).
:- comment(integral_t / 3, [summary : "Tentative value implementation of approximate integrality", amode : (integral_t(?, ?, +) is det), args : ["X" : "Tentative variables", "Epsilon" : "Allowed deviation from integrality", "MC" : "A monitored_constraint descriptor"], see_also : [eq_t / 3, neq_t / 3, tent_implements / 2], desc : html("\n\t<P>\n    \tTentative value implementation of approximate integrality constraint.\n\t</P><P>\n\tThe violatedness of the constraint is 0 if X's value is within\n\ttolerance Epsilon of the nearest integers, 1 otherwise.\n\t</P><P>\n\tThe following declaration is in effect, meaning that integral_t/3\n\tis used whenever alldifferent/1 is added to a constraint set:\n\t<PRE>\n\t:- integral_t/3 tent_implements integral/2.\n\t</PRE>\n\t</P>\n    "), eg : "\n    ?- X tent_set 3.2, CS :~ integral(X, 0.1).\n    X = X{3.2 -> 0}\n    CS = constraint_set(TotalVio{1 -> 0}, ...)\n    There is 1 delayed goal.\n    Yes (0.00s cpu)\n\n    ?- X tent_set 3.2, CS :~ integral(X, 0.1), X tent_set 3.01.\n    X = X{3.01 -> 0}\n    CS = constraint_set(TotalVio{0 -> 0}, ...)\n    There is 1 delayed goal.\n    Yes (0.00s cpu)\n    "]).
:- comment(neq_t / 3, [summary : "Tentative value implementation of $\\=/2 arithmetic disequality constraint", amode : (neq_t(?, ?, +) is det), args : ["X" : "Expression containing tentative variables", "Y" : "Expression containing tentative variables", "MC" : "A monitored_constraint descriptor"], see_also : [alldifferent_t / 2, alldifferent_t / 3, eq_t / 3, tent_implements / 2], desc : html("\n\t<P>\n    \tTentative value implementation of disequality constraint.\n\t</P><P>\n\tThe violatedness of the constraint is 0 if the disequality holds,\n\t1 otherwise.\n\t</P><P>\n\tThe following declaration is in effect, meaning that eq_t/3\n\tis used whenever $\\= /2 is added to a constraint set:\n\t<PRE>\n\t:- neq_t/3 tent_implements $\\= /2.\n\t</PRE>\n\t</P>\n    "), eg : "\n    ?- [X, Y] tent_set [3, 4], CS :~ (X $\\= Y).\n    X = X{3 -> 0}\n    Y = Y{4 -> 0}\n    CS = constraint_set(TotalVio{0 -> 0}, ...)\n    There is 1 delayed goal.\n    Yes (0.00s cpu)\n\n    ?- [X, Y] tent_set [3, 3], CS :~ (X $\\= Y).\n    X = X{3 -> 0}\n    Y = Y{3 -> 0}\n    CS = constraint_set(TotalVio{1 -> 0}, ...)\n    There is 1 delayed goal.\n    Yes (0.00s cpu)\n    "]).
