forked from Gecode/MPG
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathv.tex.in
executable file
·3804 lines (3378 loc) · 131 KB
/
v.tex.in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
% -*- mode: LaTeX; -*-
%% FILES: PARTONLY
%% Additional files to be included:
%% \litfile{a}{a}{template.vis}\\
\chapter{Getting started}
\label{chap:v:started}
This chapter outlines how a new variable type can be programmed
with Gecode. The chapter (and the entire part on programming
variables) chooses integer interval variables as its running
example.
\paragraph{Overview.}
An overview of what needs to be designed and programmed is
presented in \autoref{sec:v:started:overview}. The structure of
how the implementation of a variable type is organized is
presented in \autoref{sec:v:started:structure}.
\begin{important}
Programming variables requires to configure and recompile
Gecode from its source code. More details can be found in
\autoref{chap:v:all}.
\end{important}
\section{Overview}
\label{sec:v:started:overview}
We are going to use \emph{integer interval variables} as the
running example for programming variables.
Integer interval variables take integer values (like the integer
variables that come pre-defined with Gecode do) but their domain
is defined by a lower and an upper bound only. That is, the
domain is always an interval. This is in contrast to the integer
variables that come with Gecode, where their domain can be any
finite set of integer values.
The focus of this part is on understanding what needs to be done
for implementing new variables, so we deliberately choose very
simple variables together with very few operations on them as an
example.
Even though integer interval variables seem not very interesting,
variants of them could in fact be interesting. For
example, the integer values used for the lower and upper bound
could be integers of arbitrary precision, or instead of integer
values one could choose floating point values.
\paragraph{What must be programmed.}
Programming variables includes the following tasks:
\begin{itemize}
\item \emph{Variable implementations} (\autoref{chap:v:varimp}):
Programming a variable implementation consists of two tasks.
\begin{itemize}
\item
The first task is to specify domain-independent
aspects of a variable implementation. This includes
specifying a name for the variable implementation type, scope
information, modification events, and propagation conditions.
From a simple specification file containing this information a
domain-independent base class for a variable implementation and
the corresponding \CPP{} definitions of modification events and
propagation conditions is generated.
The generated base class together with the definition of
modification events and propagation conditions actually become
part of Gecode's kernel. The kernel needs these definitions to
schedule propagators that have subscribed to a variable
implementation and to maintain these subscriptions during
cloning.
\item
The second task consists of programming the
domain-dependent operations of a variable implementation. This
is achieved by defining a class for a variable implementation
that inherits from the generated, domain-independent base class
and defines the respective domain operations.
\end{itemize}
\item \emph{Variables} and \emph{variable arrays}
(\autoref{chap:v:var}): As a variable is nothing but a simple
and read-only interface to a variable implementation, a
variable is obtained by inheriting from a base class for
variables that depends on the variable implementation type. The
actual programming amounts to defining read-only variable
operations that invoke the corresponding operations on the
variable's variable implementation.
Variable arrays and variable argument arrays are, as variables,
needed for modeling. Their programming requires the definition
of several traits classes so that the defined arrays can be
used with Gecode-provided functionality (for example, with the
matrix interface for arrays, see
\autoref{sec:m:minimodel:matrix}).
\item \emph{Views} (\autoref{chap:v:view}): Programming a view
depends on the type of the view: whether the view is a direct
interface to a variable implementation (a \emph{variable
implementation view}), whether it is a \emph{constant view},
or whether it is derived (a \emph{derived view}) from some
other view. As examples, we are going to implement an integer
view as a variable implementation view, minus and offset views
as derived views, and an integer constant view as a constant
view.
In addition to the classes for views, some additional functions
on views must be defined for testing in which order views are
and whether two views are shared or the same (see
\autoref{par:p:views:sameshared}).
\item \emph{Constraints} and \emph{branchings}: typically, when
implementing variables one also needs to implement constraints
and branchings for them.
The implementation of constraints for a new variable type is
not in any way different from what is described in
\autoref{part:p}.
The situation for implementing branchings is quite different:
here one would want to offer at least a common set of
variable-value branchings similar to those for integer variables
(see \autoref{sec:m:branch:int}). Gecode offers substantial
support for implementing variable-value branchings, including
support for the specification of variable and value selection
strategies, random and action-based selection of variables,
tie-breaking, filter functions, no-goods, and much more. How
to use Gecode's support for implementing variable-value
branchings is detailed in \autoref{chap:v:branch}.
In case one implements \emph{reified} constraints, it is
possible to use these reified constraints together with Boolean
expressions and relations as provided by the MiniModel modeling
support. For an example, please consider
\autoref{sec:m:minimodel:boolmisc}.
\item \emph{Tracing} support (\autoref{chap:v:trace}): in order
to support variable tracing, one needs to
implement a few classes.
Only so-called \emph{trace views} require some effort, the
remaining functionality that needs to be implemented is
straightforward and can be done by following a simple recipe.
\end{itemize}
\paragraph{Putting everything together.}
Even though we are presenting the implementation of integer
interval variables only as an example, \autoref{chap:v:all} shows
how everything is put together. This includes examples of
propagators, post functions using various views, and a
simple script (Golomb rulers, see \autoref{chap:c:golomb}) using
integer interval variables.
It also shows how Gecode must be configured and
compiled such that integer interval variables are supported by
Gecode's kernel.
\section{Structure}
\label{sec:v:started:structure}
\begin{figure}[p]
\insertlitcode{int.hh}
\caption{The header file for integer interval variables}
\label{fig:v:started:header}
\end{figure}
The implementation of integer interval variables is contained in
a single header file \DOWNLOAD{int.hh}{\texttt{int.hh}}, which is
shown in \autoref{fig:v:started:header}.
\paragraph{Namespaces.}
The implementation is contained in the namespace \?MPG? (for
\?M?odeling and \?P?rogramming with \?G?ecode) to avoid
name-clashes with functionality provided by Gecode. To keep the
implementation of integer interval variables concise, some important
definitions in the \?Gecode? namespace are made available by
\?using? declarations (see \autoref{fig:v:started:header}).
Similar to the organization of namespaces in Gecode, definitions
that are used for modeling (variables and variable arrays) are
contained in the namespace \?MPG?, while definitions that are
used for programming (variable implementations, views, branchers,
and additional support) are in the namespace \?MPG::Int?.
As the structure of namespaces matters (part of the support for
variable arrays must be defined inside the \?Gecode? namespace),
each program fragment is shown in its appropriate namespace.
As an example, consider the definition of exceptions. Two are
thrown by the constructor of the integer interval
variable, in case the variable domain is ill-specified. The third
exception is thrown when the variable or value selection for a
branching is unknown.
\begin{samepage}
The exceptions are defined as follows:
\insertlitcode{int.hh:exceptions}
\end{samepage}
As discussed above, \?Exception? is \?Gecode::Exception? (see
\gecoderef[class]{Exception}) and has been introduced by a
\?using? declaration.
\paragraph{Naming scheme.}
The naming scheme follows the same naming scheme for integer
variables as defined by Gecode (albeit defined in the
namespace \?MPG? instead of \?Gecode?):
\begin{itemize}
\item Variable implementations: The base class is named
\?IntVarImpBase? whereas the variable implementation class is
named \?IntVarImp?. The names of modification events start with
\?ME_INT_? whereas the names of propagation conditions start
with \?PC_INT_?. As mentioned above, these classes and
identifiers are defined within the namespace \?MPG::Int?.
\item Variables and variable arrays: Integer interval variables
are implemented by the class \?IntVar?. Variable arrays of
integer interval variables are implemented by the class
\?IntVarArray?, whereas the corresponding variable argument
array is implemented by the class \?IntVarArgs?. These classes
are defined in the namespace \?MPG?.
\item Views: the respective views are implemented by classes
\?IntView?, \?ConstIntView?, \?MinusView?, and \?OffsetView?.
They are all defined within the namespace \?MPG::Int?.
\item Branchings: how variables and values are selected is
implemented by functions such as \?INT_VAR_NONE()? or
\?INT_VAL_MIN()? and the actual branching is implemented by a
single \?branch()? function. The good news is that no actual
brancher must in fact be implemented, even though a number of
rather straightforward support definitions must be
implemented (which are contained in the namespace \?MPG::Int?).
\item Variable tracing: variable tracers are implemented by the
class \?IntTracer? (a type definition), a standard variable
tracer is implemented by the class \?StdIntTracer?, a variable
trace recorder by a class \?IntTraceRecorder? (also a type
definition), and an integer trace delta by a class
\?IntTraceDelta?. Additionally, trace views are implemented by
a class \?Int::IntTraceView? and some traits must be defined.
\end{itemize}
\paragraph{Inline functions as simplification.}
All functions, be they member or non-member functions are defined
as \?inline?. The reason for this is to make it easier to follow
the example, as only the single header file
\DOWNLOAD{int.hh}{\texttt{int.hh}} is needed. In a real
implementation one would move the definitions of some functions to
a source file and only leave the declaration of the functions in
the header file. This is in particular true for many of the functions
defined in \autoref{chap:v:branch}.
\chapter{Variable implementations}
\label{chap:v:varimp}
This chapter describes how variable implementations can be
programmed with Gecode. The chapter uses integer interval variables
as introduced in \autoref{chap:v:started} as its running example.
\paragraph{Overview.}
The design of integer interval variables is detailed in
\autoref{sec:v:varimp:design}. After having finalized the design,
\autoref{sec:v:varimp:spec} explains how the domain-independent
base class for the variable implementation together with
definitions of modification events and propagation conditions
can be generated from a simple specification.
\autoref{sec:v:varimp:varimp} shows how the actual variable
implementation is programmed from the generated base class for a
variable implementation. \autoref{sec:v:varimp:add} provides an
overview of additional options for generating a variable
implementation base class from its specification.
\section{Design decisions}
\label{sec:v:varimp:design}
Before starting with the description of the implementation of
integer interval variables, let us detail their design. This
includes the design of the variable domain including access and
modification operations, deltas for advisors (see
\autoref{chap:p:advisors}), modification events, and propagation
conditions.
\paragraph{Variable domain and operations.}
Unsurprisingly, the variable domain of an integer variable
implementation is represented by two integers \?l? (lower bound)
and \?u? (upper bound). The variable implementation provides
access operations \?min()? and \?max()? that return these
integers.
To modify an integer interval variable implementation, the
operation \?gq(home,n)? modifies the domain such that its values
must be greater or equal to~\?n?, whereas the operation \?lq(home,n)?
modifies the domain such that its values must be less or equal
to~\?n?.
The values \?l? and \?u? can only be initialized (when creating a
new variable, see \autoref{sec:v:var:var}) and modified such that
they obey the following invariants:
\begin{enumerate}
\item The domain is never empty, that is,
$\mathtt{l}\leq\mathtt{u}$.
\item The domain values never exceed the limits defined by
(\?INT_MAX? is the largest possible value for an \?int?):
\insertsmalllitcode{int.hh:limits}
That is,
$\mathtt{Int::Limits::min}\leq \mathtt l\leq \mathtt u\leq\mathtt{Int::Limits::max}$.
\end{enumerate}
The choice of values for \?Limits::min? and \?Limits::max? are
motivated by simplicity only. To keep the example propagators
used in \autoref{chap:v:all} simple, the limits are chosen such
that the addition and subtraction of two integer values within
the limits do not lead to numerical overflow. A real-life
variable implementation would try to make as many values as
possible available for a variable domain, see for example
\autoref{sec:m:integer:limits}.
\tip{Correctness matters}{ While the decision to restrict the
possible values of a variable implementation is motivated by
simplicity, the decision for a real-life variable
implementation is absolutely essential.
Being unclear about which values can correctly be maintained by
a variable implementation, not ensuring that no numerical
overflow occurs, or not checking for the necessary invariants
when a new variable is created, renders the very idea of
constraint programming obsolete: that whenever a solution is
found by Gecode, it \emph{actually happens to be a solution}.
Hence correctness does not only matter for implementing
propagators and branchers but also for getting the basic design
of variables right.
}
\paragraph{Assigned variables.}
An integer interval variable is assigned iff $\mathtt l=\mathtt
u$.
\paragraph{Deltas for advisors.}
We design the delta information for an advisor computed by a
modification operation on the variable implementation to be an
interval as well. The interval defines the values that are
removed by a modification operation. Due to the nature of the
modification operations \?lq()? and \?gq()?, the removed values
always form an interval.
The design of deltas to be used by advisors for a variable
implementation depends directly on the design of the modification
operations provided by a variable implementation. For example, if
our integer interval variable implementation also featured an
operation \?eq()? to assign a variable implementation to a value,
then one also would have to choose a different design for the
delta information. Assume a variable implementation with domain
$\range{\mathtt{l}}{\mathtt{u}}$ and that the modification
operation \?eq(home,n)? is executed where $\mathtt{l}<\mathtt
n<\mathtt u$. Then one could design the delta information to
either accurately represent the set of removed values
$\range{\mathtt{l}}{\mathtt{n-1}}\cup\range{\mathtt{n+1}}{\mathtt{u}}$
or to provide support for signaling that the domain has changed
arbitrarily (this is the design chosen for integer variables in
Gecode, see \autoref{par:p:advisors:delta}).
\paragraph{Modification events.}
Any variable implementation must support the mandatory events for
no modification (to be implemented as \?ME_INT_NONE?), for
failure (to be implemented as \?ME_INT_FAILED?), and for
assignment to a value (to be implemented as \?ME_INT_VAL?).
The additional events must be chosen such that they take the
following two aspects into account:
\begin{itemize}
\item The modification operations should return meaningful
values that describe how the domain of a variable
implementation has changed. They must return \?ME_INT_VAL? if
the variable implementation becomes assigned. Otherwise, we choose
to return \?ME_INT_MIN? if the lower bound changes
and to return \?ME_INT_MAX? if the upper bound changes.
\item When a new propagator is posted and the propagator subscribes to some
views (and hence to some variable implementations), the
propagator must be scheduled with respect to some
modification event. This modification event should capture that
``somehow the variable has changed for the propagator''. In
case an integer interval variable implementation is not yet
assigned (otherwise the propagator will be scheduled with the
modification event \?ME_INT_VAL? anyway), we use an additional
modification event \?ME_INT_BND? capturing that one or both of
the bounds have changed.
\end{itemize}
Again, there is quite some degree of freedom in the choice of
modification events. Another design would be to only provide the
modification event \?ME_INT_BND? instead (apart from the mandatory
modification events). An important aspect in which design to
choose is the relation between modification events and
propagation conditions to be discussed below.
\paragraph{Propagation conditions.}
\label{par:v:varimp:design:pc}
To make our example variable implementations sufficiently
interesting, we design the propagation conditions such that they
can take full advantage of the modification events.
That is, apart from the mandatory propagation condition for not
creating any subscription (to be implemented as \?PC_INT_NONE?) and the
mandatory propagation condition for an assigned variable
implementation (to be implemented as \?PC_INT_VAL?), we have
three propagation conditions as follows:
\begin{itemize}
\item \?PC_INT_MIN?: schedule a propagator if the lower bound of
a variable implementation changes.
\item \?PC_INT_MAX?: schedule a propagator if the upper bound
changes.
\item \?PC_INT_BND?: schedule a propagator if lower or upper
bound changes.
\end{itemize}
This design can also be reformulated in terms of modification events
that are generated by a modification operation:
\begin{itemize}
\item \?PC_INT_MIN?: schedule a propagator for \?ME_INT_VAL?,
\?ME_INT_MIN?, and \?ME_INT_BND?.
\item \?PC_INT_MAX?: schedule a propagator for \?ME_INT_VAL?,
\?ME_INT_MAX?, and \?ME_INT_BND?.
\item \?PC_INT_BND?: schedule a propagator for \?ME_INT_VAL?,
\?ME_INT_MIN?, \?ME_INT_MAX?, and \?ME_INT_BND?.
\end{itemize}
A simpler design would be to have the single non-mandatory propagation
condition \?PC_INT_BND?. The decision which design is best is not
straightforward, as the tradeoff between the cost for additional
propagation conditions (see below) and the gain from avoiding
propagator executions depends on many different aspects. For a
discussion and an evaluation in the context of Gecode's integer
variables, see~\cite[Section~5]{SchulteStuckey:TOPLAS:2008}.
\paragraph{Costs and limits for modification events and
propagation conditions.}
\label{par:v:varimp:design:cost}
The cost per each individual modification event and propagation
condition is as follows:
\begin{itemize}
\item Assume that a variable implementation uses $n$ different
modification events (including the mandatory ones). The size of
$n$ does not affect efficiency. To represent these modification
events, the Gecode kernel reserves $\lceil\log_2 (n-1)\rceil$
bits in each propagator for maintaining modification event
deltas, see \autoref{sec:p:domain:med}.
The totally available number of bits for all variable
implementation types used by Gecode is~$32$ (independent of
whether Gecode is run on a $32$~bit or $64$~bit platform). That
is, if we assume less than ten modification events per variable
implementation type, the Gecode kernel can support at least ten
different variable implementation types.\footnote{If you ever
exceed this limit, please let us know. Adding more bits is
easy, even though we do not expect that to happen anytime
soon.}
\item The number of different propagation conditions $m$ per
variable implementation type is only limited by the largest
value of an unsigned integer in \CPP.
For each propagation condition, every variable implementation
needs a $32$-bit word, that is a variable implementation
requires at least $O(m)$ space (which is typically dwarfed by
the space consumed for actually storing the subscriptions of a
propagator or an advisor to a variable implementation).
Subscribing to a variable implementation requires $O(m)$ time.
Canceling a subscription with propagation condition $p$
requires $O(m+k)$ time, where $k$ is the number of
subscriptions with propagation condition $p$.
\end{itemize}
\section{Base definitions}
\label{sec:v:varimp:spec}
The variable implementation base class together with definitions
of modification events and propagation conditions are not
programmed but are generated from a simple specification file.
The specification contains three sections: a general
section for naming, a section for modification events, and a
section for propagation conditions.
In the following we describe how to turn the parts of the design
from the previous section that is concerned with modification
events and propagation conditions into the specification. The
member functions of the generated base class are used and
explained in the next section.
\paragraph{General section.}
\begin{figure}
\litcmdblock{
\noindent\litfile{variable implementation specification}{variable implementation specification}{int.vis}\\
\lits\lits{}\litkw{[General]}\\
\lits\lits{}Name:\lits\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}Int\\
\lits\lits{}Namespace:\lits\lits{}\lits{}MPG::Int\\
\lits\lits{}\litref{lit:vis:modevent}{modification\lits{}events}\\
\lits\lits{}\litref{lit:vis:propcond}{propagation\lits{}conditions}\\
\lits\lits{}\litkw{[End]}
}
\caption{Variable implementation specification}
\label{fig:v:varimp:vis}
\end{figure}
The specification file (named \texttt{int.vis}, where \?vis?
stands for \?v?ariable \?i?mplementation \?s?pecification;
however the file extension does not matter) is
shown in \autoref{fig:v:varimp:vis}. The specification file must
start with \litkw{[General]} defining the start of the general
section and must end with a line \litkw{[End]}. The \?Name? option defines the names of the entities to
be generated. In our example, a variable implementation base
class \?IntVarImpBase? (that is, the specified name is prepended
to \?VarImpBase?) generated, the identifiers for
modification events start with \?ME_INT_? (that is, the specified
name is put after the \?ME_? in capital letters), and the
identifiers for propagation conditions start with \?PC_INT_?. All
these definitions are contained within the namespace as defined
by the \?Namespace? option.
The general section (and also the other sections discussed below)
supports additional specification options, see
\autoref{sec:v:varimp:add} for a summary and a specification file
template for download.
\paragraph{Modification event section.}
\begin{figure}
\litcmdblock{%
\noindent\litlabel{lit:vis:modevent}{modification events}\\
\lits\lits{}\litkw{[ModEvent]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}FAILED=FAILED\\
\lits\lits{}\litkw{[ModEvent]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}NONE=NONE\\
\lits\lits{}\litkw{[ModEvent]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}VAL=ASSIGNED\\
\lits\lits{}Combine:\lits{}\lits{}\lits{}\lits{}\lits{}VAL=VAL,\lits{}MIN=VAL,\lits{}MAX=VAL,\lits{}BND=VAL\\
\lits\lits{}\litkw{[ModEvent]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}BND=SUBSCRIBE\\
\lits\lits{}Combine:\lits{}\lits{}\lits{}\lits{}\lits{}VAL=VAL,\lits{}MIN=BND,\lits{}MAX=BND,\lits{}BND=BND\\
\lits\lits{}\litkw{[ModEvent]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}MIN\\
\lits\lits{}Combine:\lits{}\lits{}\lits{}\lits{}\lits{}VAL=VAL,\lits{}MIN=MIN,\lits{}MAX=BND,\lits{}BND=BND\\
\lits\lits{}\litkw{[ModEvent]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}MAX\\
\lits\lits{}Combine:\lits{}\lits{}\lits{}\lits{}\lits{}VAL=VAL,\lits{}MIN=BND,\lits{}MAX=MAX,\lits{}BND=BND}
\caption{Modification event section}
\label{fig:v:varimp:vis:me}
\end{figure}
Every modification event requires a definition that is
preceded by a line containing \litkwt{[ModEvent]} as shown in
\autoref{fig:v:varimp:vis:me}. The option \?Name? defines the
name of the modification event (in fact, just the part after
\?ME_INT_? for our example). The values on the right-hand
side of \?=? specify that some modification events are special:
\begin{itemize}
\item The modification events named \?FAILED? (that is,
\?ME_INT_FAILED?) and \?NONE? (that is, \?ME_INT_NONE?)
are defined to be the events for failure (\?=FAILED?) and no
change (\?=NONE?).
\item The modification event named \?VAL? is defined to be the
event when a variable implementation becomes assigned
(\?=ASSIGNED?) to a
value.
\item The modification event named \?BND? is defined to be used
for scheduling a propagator when the propagator subscribes to a
non-assigned variable implementation (\?=SUBSCRIBE?).
\end{itemize}
Any variable implementation must define special events with
\?=NONE?, \?=FAILED?, \?=ASSIGNED?, and \?=SUBSCRIBE?. In case
there are only three modification events (all of them special
with \?=NONE?, \?=FAILED?, \?=ASSIGNED?), the modification event
used for scheduling a propagator (that is, \?=SUBSCRIBE?) is
defined to be the event for a variable becoming assigned (that
is, \?=ASSIGNED?).
The section for modification events also defines how
modification events are combined with a \?Combine?
option. The combination of modification events is needed for the
correctness of scheduling propagators and also for
modification event deltas, see \autoref{sec:p:domain:med}. An
entry $l=r$ for the modification event $m$ defines that $m$
combined with $l$ is $r$.
The definition of the combination of modification events can be
expressed as a table:
\begin{center}\ttfamily
\begin{tabular}{c||c|c|c|c|}
&VAL&MIN&MAX&BND\\\hline\hline
VAL&VAL&VAL&VAL&VAL\\\hline
MIN&VAL&MIN&BND&BND\\\hline
MAX&VAL&BND&MAX&BND\\\hline
BND&VAL&BND&BND&BND\\\hline
\end{tabular}
\end{center}
This table is exactly what is specified by the \?Combine?
options. The special modification events \?NONE? and
\?FAILED? do not have a \?Combine? option.
We will not present the full mathematical detail of the
properties that must hold for the combination of modification
events, the theory is presented
in~\cite[Section~5.5]{Tack:PhD:2009}.
\paragraph{Propagation condition section.}
\begin{figure}
\litcmdblock{%
\noindent\litlabel{lit:vis:propcond}{propagation conditions}\\
\lits\lits{}\litkw{[PropCond]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}NONE=NONE\\
\lits\lits{}\litkw{[PropCond]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}VAL=ASSIGNED\\
\lits\lits{}ScheduledBy:\lits{}VAL\\
\lits\lits{}\litkw{[PropCond]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}BND\\
\lits\lits{}ScheduledBy:\lits{}VAL,\lits{}BND,\lits{}MIN,\lits{}MAX\\
\lits\lits{}\litkw{[PropCond]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}MIN\\
\lits\lits{}ScheduledBy:\lits{}VAL,\lits{}BND,\lits{}MIN\\
\lits\lits{}\litkw{[PropCond]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}MAX\\
\lits\lits{}ScheduledBy:\lits{}VAL,\lits{}BND,\lits{}MAX}
\caption{Propagation condition section}
\label{fig:v:varimp:vis:pc}
\end{figure}
Every propagation condition requires a definition that is
preceded by a line containing \litkwt{[PropCond]} as shown in
\autoref{fig:v:varimp:vis:pc}. The option \?Name? defines the
name of the propagation condition (in fact, just the part after
\?PC_INT_? for our example). The values on the right-hand
side of \?=? specify that some propagation conditions are special:
\begin{itemize}
\item The propagation condition named \?NONE? (that is, \?PC_INT_NONE?)
is defined to be the propagation condition for not creating any
subscription (\?=NONE?).
\item The propagation condition named \?VAL? (that is,
\?PC_INT_VAL?) is defined to be the condition when a propagator
wants to subscribe to the event that a variable implementation
becomes assigned (\?=ASSIGNED?).
\end{itemize}
Any variable implementation must define the special propagation conditions
\?=NONE? and \?=ASSIGNED?.
For each propagation condition (but for \?=NONE?), it must be
defined by a \?ScheduledBy? option which modification events
schedule a propagator for execution. That is, when defining a
propagation condition $p$, an entry $m$ in the list of
modification events defines the following: a propagator
subscribed to a variable implementation $x$ with propagation
condition $p$ is scheduled for execution when a modification
operation on $x$ returns the modification event $m$. The
modification events in our example correspond to the design
presented in \autoref{par:v:varimp:design:pc}.
\section{Variable implementation}
\label{sec:v:varimp:varimp}
\begin{figure}
\insertlitcode{int.hh:variable implementation}
\caption{Variable implementation}
\label{fig:v:varimp:varimp}
\end{figure}
The variable implementation for integer interval variables is
shown in \autoref{fig:v:varimp:varimp}. As discussed in the
previous sections, the variable implementation inherits from the
generated base class \?IntVarImpBase? and implements a lower
bound \?l? and an upper bound \?u?.
\paragraph{Access operations.}
Every variable implementation must implement a member function
\?assigned()? that tests whether the variable is assigned to a
value:
\insertlitcode{int.hh:varimp:assignment test}
The test for assignment is used in the implementation of other member
functions of the variable implementation. Furthermore, variables
and views automatically provide implementations of a member
function \?assigned()? that calls the \?assigned()?
function of their variable implementation.
\begin{samepage}
The access operations for the lower and upper bound are
straightforward. Here, and in the following, we only show
one of the operations, the operation for the other bound is
analogous:
\insertlitcode{int.hh:varimp:access operations}
\end{samepage}
\paragraph{Modification operations.}
The modification operations must notify the Gecode kernel if a
variable implementation is modified. As a description how a
variable implementation changes, they must
pass a modification event and
delta information for advisors to a member function \?notify()?.
The \?notify()? function executes subscribed advisors and
schedules subscribed propagators (depending on the passed
modification event and the propagators' propagation conditions).
The \?notify()? function is inherited from the generated variable
implementation base class and depends on the specified
modification events and propagation conditions.
The delta information is implemented as discussed in
\autoref{sec:v:varimp:design} as an interval with lower and upper
bound:
\insertlitcode{int.hh:varimp:delta for advisors}
The actual modification operations first test whether the
variable implementation does not require modification or whether
the operation fails and only then perform the actual modification.
Before updating the upper bound \?u? to \?n?, the
\?lq()? operation creates the delta information \?d? that describes
that values between \?n+1? and \?u? are being removed.
The \?notify()? function is given the \?home? space, a
modification event, and the variable delta \?d? as argument. The
modification event passed to \?notify()? must capture how the
domain has changed. In particular, it must reflect whether the
variable implementation has been assigned. The \?notify()?
function executes the advisors subscribed to this variable
implementation and schedules all subscribed propagators with
appropriate propagation conditions. Note that the \?notify()?
function returns a modification event. In case an advisor reports
failure after its execution, \?notify()? returns \?ME_INT_FAILED?. Otherwise it
returns the modification event that has been passed as argument:
\insertlitcode{int.hh:varimp:modification operations}
If a modification operation fails it must return \?ME_INT_FAILED?
as modification event and must call the \?fail()? function. The
\?fail()? function is similar to \?notify()? and executes
advisors that have registered to be executed on failure. For
convenience, the \?fail()? function itself returns
\?ME_INT_FAILED?.
\tip{Variable implementations must always be consistent}{
Even if a modification operation fails, the data structures for
the variable implementation must be still consistent. That is,
all operations must still work. See also
\autoref{sec:m:integer:empty}.
}
\paragraph{Delta information access.}
The variable implementation must also implement functions that
provide access to the delta information:
\insertlitcode{int.hh:varimp:delta information}
This construction appears nonsensical at first sight, however
there are two good reasons why a variable implementation
interprets the information stored in the delta information (of
course, in that case one would have to declare the operation as
\?const? but not \?static?). First, the variable implementation
can change the information based on its own state. Second, the
very same idea is needed for views (see
\autoref{sec:v:view:offset} for an example) and hence this design
keeps the interfaces of views and variable implementations as
similar as possible.
\paragraph{Subscriptions.}
A variable implementation must implement \?subscribe()?
operations for both propagators and advisors. The
implementation of these operations always follow the
same structure as shown below.
The reason why these functions have to be implemented in the variable
implementation class even though they are (in slightly different
form) already defined in the variable implementation base class
is that they require information about whether
a variable implementation is assigned. The
definitions are as follows:
\insertlitcode{int.hh:varimp:subscriptions}
\paragraph{Re-scheduling.}
A variable implementation must implement a \?reschedule()?
operation for propagators. The
implementation of this operation is almost identical to the
\?subscribe()? member function discussed previously. The
definition is as follows:
\insertlitcode{int.hh:varimp:re-scheduling}
\paragraph{Copying during cloning.}
Copying a variable implementation during cloning is implemented
by a constructor and a \?copy()? function. The constructor is
straightforward and the \?copy()? function only creates a new
variable implementation if the variable implementation has not
been copied before. If it has been copied before (that is,
\?copied()? returns \?true?), the \?copy()? function must return
the forwarding pointer to the previously created copy as follows:
\insertlitcode{int.hh:varimp:copying}
\paragraph{Additional inherited member functions.}
\begin{figure}
\begin{center}
\begin{tabular}{ll}
\multicolumn{2}{c}{\textbf{access operations}}\\
\?degree()? & returns degree (number of subscriptions)\\
\?afc()? & returns accumulated failure count\\
\\
\multicolumn{2}{c}{\textbf{subscriptions}}\\
\?cancel()? & cancel subscription of propagator\\
\?cancel()? & cancel subscription of advisor\\
\\
\multicolumn{2}{c}{\textbf{scheduling support}}\\
\?schedule()? & schedule propagator\\
\?reschedule()? & re-schedule propagator\\
\\
\multicolumn{2}{c}{\textbf{modification event deltas}}\\
\?me()? & extract modification event\\
\?med()? & construct modification event delta\\
\\
\multicolumn{2}{c}{\textbf{delta information access}}\\
\?modevent()? & return modification event from delta\\
\end{tabular}
\end{center}
\caption{Summary of member functions predefined by variable implementations}
\label{fig:v:varimp:inherited}
\end{figure}
In addition to the constructor and the member functions defined
and used by our variable implementation, several other member
functions are typically just inherited and are defined by the
class \gecoderef[class]{VarImp}. The most important inherited
member functions are summarized in
\autoref{fig:v:varimp:inherited}. For an explanation of degree
and accumulated failure count, see
\autoref{sec:m:branch:shared}.
\section{Additional specification options}
\label{sec:v:varimp:add}
This section provides an overview of additional specification
options not discussed in \autoref{sec:v:varimp:spec}.
\paragraph{Comments.}
Any line starting with \?#? is discarded and hence can serve as a
comment in the specification file.
\paragraph{Generating headers, footers, and comments.}
Any text after the options for a \litkwt{[ModEvent]} and
\litkwt{[PropCond]} definition until the next definition is added
to the generated \CPP-code before the generated identifier
definition. This can be used for defining comments to be added to
the generated \CPP-code. For example, by
\litcmdblock{%
\lits\lits{}\litkw{[PropCond]}\\
\lits\lits{}Name:\lits{}\lits{}\lits{}\lits{}\lits{}\lits{}NONE=NONE\\
\lits\lits{}// Propagation condition to be ignored\\
\lits\lits{}\litkw{[PropCond]}\\
\lits\lits{}\litanon}
the comment
\begin{code}
// Propagation condition to be ignored
\end{code}
is put before the definition of the generated
propagation condition.
Related support exists for putting a header before (or a footer
after) all generated definitions for modification events and
propagation conditions: The text following
\litkwt{[ModEventHeader]}, \litkwt{[ModEventFooter]},
\litkwt{[PropCondHeader]}, and \litkwt{[PropCondFooter]} is
inserted at the respective places in the generated code.
\paragraph{Conditional compilation.}
Giving an option \texttt{Ifdef} in the general section
followed by some \CPP-preprocessor identifier \?IDENT? wraps the
entire generated code in preprocessor directives as follows:
\begin{code}
#ifdef IDENT
...
#endif
\end{code}
By this, the Gecode kernel can be compiled with or without a
particular variable type without being forced to reconfigure the
Gecode kernel, see also \autoref{sec:v:all:conf}.
\paragraph{Explicitly disposing variable implementations.}
\label{par:v:varimp:dispose}
Our example variables are entirely space-allocated and do not
require external memory or other resources. However, for some
variable types, the variable implementation might use external
resources or memory that is not space-allocated and must
explicitly be freed.
For an example, suppose the integer interval variables had been
implemented by using arbitrary precision integers for the lower
and upper bound and that these bounds must explicitly be freed.
By specifying in the general section
\litcmdblock{%
\lits\lits{}Dispose:\lits{}true
}
and implementing in the variable implementation class a
\?dispose(Space& home)? member function, all variable
implementations are disposed by calling their \?dispose()?
functions. The variable implementations are disposed when their
home space is deleted.
Additionally, an object must be created that controls the
disposal of variable implementations. Assume that our example
integer variables used external memory and that its specification
file contains
\litcmdblock{%
\lits\lits{}Dispose:\lits{}true
}
and that \?MPG::IntVarImp? implements a \?dispose()? function.
Then, your program must
create a variable implementation disposer as follows:
\begin{code}
Gecode::VarImpDisposer<MPG::IntVarImp> disposer;
\end{code}
The \?disposer? object must be initialized before the first
variable using \?MPG::IntVarImp? is created.
\paragraph{Reserving bits.}
A limited number of bits $b$ can be reserved within each variable
implementation by specifying in the general section
\litcmdblock{%
\lits\lits{}Bits:\lits{}$b$
}
Then, the variable implementation can get a reference to a value
of type \?unsigned int? by calling the member function \?bits()?
where the least $b$ bits can be used freely. However, the maximal
number of subscriptions (both propagators and advisors) for that
variable implementation type is reduced from $2^{31}-1$ to
$2^{31-b}-1$. Furthermore, any attempt to use more than the
specified number of bits will crash Gecode in a truly
spectacular fashion!
\paragraph{Specification file template.}
The \DOWNLOAD{template.vis}{specification template} contains all
possible specification options to assist in defining your own
variable types.
\chapter[Variables and variable arrays]{Variables and\\variable arrays}
\label{chap:v:var}
This chapter describes how variables can be programmed from
variable implementations and how variable arrays and variable argument
arrays can be programmed. The chapter uses integer interval
variables as introduced in \autoref{chap:v:started} together with
their implementations as defined in \autoref{chap:v:varimp} as
its running example.
\paragraph{Overview.}
How integer interval variables are implemented is detailed in
\autoref{sec:v:var:var}. Variable arrays and variable argument
arrays are discussed in \autoref{sec:v:var:array}.
\section{Variables}
\label{sec:v:var:var}
\begin{figure}
\insertlitcode{int.hh:var:variable}
\caption{Variable programmed from a variable implementation}
\label{fig:v:var:var}
\end{figure}
As a variable is just a read-only interface to a variable
implementation, its implementation is straightforward.
The definition of integer variables is shown in
\autoref{fig:v:var:var}. The copy constructor uses the
member function \?varimp()? that returns the pointer to the
variable's variable implementation. Note that every variable must
have a constructor that takes a pointer to the corresponding
variable implementation as argument.
Note that within the class \?IntVar?, a pointer to the
corresponding variable implementation is available as protected