:- module(changeset).
:- export monitor_changes / 6.
:- export monitor_changes_arr / 5.
:- comment(summary, "Compute sets of modified variables").
:- comment(author, "Joachim Schimpf, IC-Parc").
:- comment(copyright, "Cisco Systems, Inc.").
:- comment(date, "$Date: 2006/09/23 01:53:22 $").
:- comment(monitor_changes / 6, [summary : "Monitor variables for modifications", amode : monitor_changes(+, +, +, +, +, -), args : ["Vars" : "A list containing variables", "Templates" : "A list of terms corresponding to the variables", "Prio" : "Priority for the monitoring demons", "CondList" : "Suspension list spec", "AttrMod" : "Suspension list attribute module", "ChangeStream" : "A lazy list of lists of changes"], desc : html("\n    Like monitor_changes_arr/5, but (instead of array indices) the\n    ChangeStream contains the elements of the Templates-list that\n    correspond to the modified variables, thus allowing arbitrary\n    information to be conveyed to the code that processes the changes.\n    <PRE>\n    [eclipse 10]: X1::1..9, X2::1..8,\n\t    monitor_changes([X1,X2],[info(1,X1),info(2,X2)], 8,\n\t\t\t    [min of fd, max of fd], fd, Stream),\n\t    X1 #> X2, X2 #>= 5.\n\n    Stream = [[info(1, X1{[6..9]})], [info(2, X2{[5..8]}), info(1, X1)]|More]\n    X1 = X1{[6..9]}\n    X2 = X2{[5..8]}\n    </PRE>\n    ")]).
:- comment(monitor_changes_arr / 5, [summary : "Monitor variables for modifications", amode : monitor_changes_arr(+, +, +, +, -), args : ["VarArr" : "A structure containing variables", "Prio" : "Priority for the monitoring demons", "CondList" : "Suspension list spec", "AttrMod" : "Suspension list attribute module", "ChangeStream" : "A lazy list of lists of changes"], desc : html("\n    This predicate monitors an array of variables for certain\n    modifications, and creates a continuous stream of lists of indices of\n    modified variables, e.g.\n    <PRE>\n\tmonitor_changes_arr(VarArr, 8, [min of fd, max of fd], fd, Stream)\n    </PRE>\n    will monitor the variables in VarArr for modifications of their min/max\n    fd-attributes. The monitor will run with a priority of 8 to 9.\n    All variable modifications that occur between two wakings of the\n    monitor will be detected by the monitor. It will then create a list\n    of indices of the modified variables, and append this list to\n    ChangeStream.\n    <PRE>\n\t[eclipse 4]: X1::1..9, X2::1..8,\n\t\tmonitor_changes_arr(v(X1,X2), 8,\n\t\t\t\t    [min of fd, max of fd], fd, Changes),\n\t\tX1 #> X2, X2 #>= 5.\n\n\tChanges = [[1], [2, 1]|More]\n\tX1 = X1{[6..9]}\n\tX2 = X2{[5..8]}\n    </PRE>\n    What happened here is that the first constraint X1 #> X2 caused X1 to\n    change its lower bound, therefore [1] was appended to the Changes list.\n    Then X2 #>= 5 raised the lower bound of X2 and (because X1 #> X2)\n    the lower bound of X1, therefore both variable indices [1,2] were\n    appended to the Changes list.\n    <P>\n    The priority of the monitor should be set up such that is is lower than\n    the priority of the propagation constraints. In that case, the lists\n    that get appended to ChangeStream represent exactly the set of variables\n    (without duplicates) that were modified by one propagation sequence.\n    <P>\n    Note that the ChangeStream can be used to trigger actions whenever\n    new changes get appended, for example:\n    <PRE>\n\tdelay report_changes(X) if var(X).\n\treport_changes([]).\n\treport_changes([X|T]) :-\n\t\tprintf(\"The following variables changed: %Mw%n%b\", [X]),\n\t\treport_changes(T).\n\n\n\t[eclipse 11]: X1::1..9, X2::1..8,\n\t\tmonitor_changes_arr(v(X1,X2), 8,\n\t\t\t\t\t[min of fd, max of fd], fd, Changes),\n\t\treport_changes(Changes),\n\t\tX1 #> X2, X2 #>= 5.\n\tThe following variables changed: [1]\n\tThe following variables changed: [2, 1]\n\t...\n    <PRE>\n    ")]).
