Interfaces
From CometPublic
Contents |
[edit] Store
interface Store {
void checkpoint(boolean);
void delay(boolean);
void atomic(boolean);
void pushNode();
void popNode();
Store getStore();
}
[edit] Constraint
interface Constraint {
var{boolean} isTrue();
var{int} violations();
var{int} violations(var{int});
var{int} decrease(var{int});
int getAssignDelta(var{int},int);
int getSwapDelta(var{int},var{int});
var{int}[] getVariables();
int getAssignDelta(var{int}[],int[]);
int getSwapDelta(var{int},var{int},var{int},var{int});
int getAssignDelta(var{int},int,var{int},int);
LocalSolver getLocalSolver();
void post();
void initialize();
enum-var ConstraintType getType();
}
[edit] FloatConstraint
interface FloatConstraint {
var{boolean} isTrue();
var{float} violationDegree();
var{float} violations();
float getViolations(var{int});
var{float} violations(var{int});
var{float} decrease(var{int});
float getAssignDelta(var{int},int);
float getSwapDelta(var{int},var{int});
var{int}[] getVariables();
int getAssignDelta(var{int},int,var{int},int);
}
[edit] Objective
interface Objective {
var{int} evaluation();
var{int} increase(var{int});
var{int} decrease(var{int});
var{int} flipDelta(var{boolean});
int getAssignDelta(var{int},int);
int getSwapDelta(var{int},var{int});
LocalSolver getLocalSolver();
void post();
var{int}[] getVariables();
}
[edit] FloatObjective
interface FloatObjective {
var{float} evaluation();
var{float} increase(var{int});
var{float} decrease(var{int});
var{float} flipDelta(var{boolean});
float getAssignDelta(var{int},int);
float getSwapDelta(var{int},var{int});
LocalSolver getLocalSolver();
void post();
}
[edit] Neighborhood
interface Neighborhood {
boolean accept(int);
void insert(int,Closure);
boolean accept(float);
void insert(float,Closure);
boolean hasMove();
Closure getMove();
}
[edit] ObjectiveOverBool
interface ObjectiveOverBool {
var{int} value();
var{int} flipDelta(var{boolean});
int getSwapDelta(var{boolean},var{boolean});
}
[edit] ScheduleObjective
interface ScheduleObjective {
int eval();
}
[edit] ostream
interface ostream {
void setCompactStyle();
void setNamingStyle();
void setLineStyle();
void setAddressStyle();
}
[edit] Invariant
interface Invariant {
void post(InvariantPlanner planner);
void initPropagation();
void propagateInt(boolean b,var{int} v);
LocalSolver getLocalSolver();
void propagateFloat(boolean b, var{float} v);
void propagateInsertIntSet(boolean b, var{set{int}} v, int i);
void propagateRemoveIntSet(boolean b, var{set{int}} v, int i);
}
interface InvariantPlanner {
void addSource(var{int});
void addTarget(var{int});
}
Users can extend comet and add invariants of their own that interface with the existing system. To produce a user-defined invariant, it suffices to define a class that implements the Invariant interface shown above. The class must implement the four methods above. The role of
void post(InvariantPlanner planner);
is to post the invariant inside a constraint system. The method receives as an argument a planner that one should use during the post to state the dependencies between the input variables, the invariant, and the output variables. The method addSource(var{int} v) is useful to report that variable v is an input variable that the current invariant depends on. Similarly, addTarget(var{int} v) is a method used to report that v is a variable whose value depends on the current invariant.
The method
void initPropagation();
is called automatically by comet during the planification step and gives an opportunity to the invariant to properly initialize its internal state. Note that initPropagation is called by comet when all the source variables (as defined by calls to addSource during the post) are correctly initialized.
The method
void propagateInt(boolean b,var{int} v);
is the central method that is triggered by comet during incremental updates. The method will be called by comet once for each source variable that has changed. The first argument (b) indicates whether this invocation of the method is the last one. The argument v indicates which variable triggered the propagation of the invariant. (Recall that all variables have a method getId() to obtain the unique internal variable identifier).
Finally, the method
LocalSolver getLocalSolver();
is a simple accessor that returns the LocalSolver that this invariant is defined on. Typically, the method is a one-liner that returns the localSolver whose address is in an instance variable that was initialized by the class constructor.
Once a user invariant class is defined, instances can be created and posted to the LocalSolver as any other invariant (with a post method).
[edit] Example
Consider, for example, a user-defined invariant to maintain the meetings in a social golfer problem. The skeleton of the invariant class would look like:
tuple Player { int w; int g; int s; }
class Meet implements Invariant {
LocalSolver ls;
range Weeks;
range Groups;
range Sizes;
range Golfers;
var{int}[,,] golfer;
var{int}[,] meet;
dict{var{int}->Player} map;
Meet(LocalSolver _ls,range _Weeks,range _Groups,range _Sizes,range _Golfers,var{int}[,,] _golfer) {
ls = _ls;
Weeks = _Weeks;
Groups = _Groups;
Sizes = _Sizes;
Golfers = _Golfers;
golfer = _golfer;
var{int} _meet[Golfers,Golfers](ls) := 0;
map = new dict{var{int}->Player}();
meet = _meet;
}
var{int}[,] getMeet() { return meet; }
LocalSolver getLocalSolver() { return ls;}
void post(InvariantPlanner planner) {
forall(w in Weeks,g in Groups,s in Sizes) {
planner.addSource(golfer[w,g,s]);
map{golfer[w,g,s]} = new Player(w,g,s);
}
forall(p in Golfers,q in Golfers)
planner.addTarget(meet[p,q]);
}
void initPropagation() {
forall(w in Weeks,g in Groups)
forall(s in Sizes, t in Sizes: s < t) {
meet[golfer[w,g,s],golfer[w,g,t]]++;
meet[golfer[w,g,t],golfer[w,g,s]]++;
}
}
void propagateInt(bool b,var{int} v) {
Player p = map{v};
int ov = v.getOld();
int nv = v;
forall(t in Sizes: t != p.s) {
int o = golfer[p.w,p.g,t];
meet[ov,o]--;
meet[o,ov]--;
meet[nv,o]++;
meet[o,nv]++;
}
}
/*
* The following three methods are required to adhere to the interface but will not be called
* in the current example.
*/
void propagateFloat(boolean b, var{float} v){
cout << "propagateFloat Not Yet Implemented" << endl;
}
void propagateInsertIntSet(boolean b, var{set{int}} v, int i){
cout << "propagateInsertIntSet Not Yet Implemented" << endl;
}
void propagateRemoveIntSet(boolean b, var{set{int}} v, int i){
cout << "propagateRemoveIntSet Not Yet Implemented" << endl;
}
}
Note that the Meet constructor simply creates an internal Map datastructure to easily retrieve for every source variable its player and define a 2D matrix meet of variables (the outputs). The post method fills the map and sets up the source and target dependencies. InitPropagation simply computes the number of meetings for each pair of players. Finally the propagateInt method is called whenever a golfer assignment changes. It retrieves the details of the player from the map, picks up the old assignment and updates the meet matrix. Note that since the meet matrix entries were marked as output variables in the post, the changes done here on the meet variable will schedule the invariants that depends on meet. Naturally, the class provides a getMeet() method to return the meetings matrix so that other invariants can be defined from these meeting variables.

