bound.c
2.43 KB
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
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "fdc_int.h"
#include "store.h"
#include "bound.h"
#include "constraints.h"
#include "util.h"
bool _fd_optimising = false;
struct _fd_bound_data {
int value;
C_VAR_T variable;
fd_constraint constraint;
int (*check)(fd_constraint, _fd_store, int *);
int (*valid)(int, int);
int (*compare)(fd_constraint, _fd_store, _fd_store);
bool (*bound)(fd_constraint, int);
};
_fd_bound_data *_fd_bound = NULL;
_fd_bound_data *_fd_init_bound(int n, C_VAR_T v, fd_constraint c,
int (*f)(fd_constraint, _fd_store, int *),
int (*g)(int, int),
int (*h)(fd_constraint, _fd_store, _fd_store),
bool (*i)(fd_constraint, int))
{
_fd_bound_data *b;
if (_fd_bound)
fd__fatal("trying to set a 2nd optimisation constraint");
if ((b = malloc(sizeof(*_fd_bound))) == NULL)
fd__fatal("could not allocate memory for the optimisation bound");
b->value = n;
b->variable = v;
b->constraint = c;
b->check = f;
b->valid = g;
b->compare = h;
b->bound = i;
_fd_bound = b;
_fd_optimising = true;
return b;
}
bool _fd_set_bound(int value)
{
assert(_fd_bound != NULL);
if (!_fd_bound->valid(_fd_bound->value, value))
return false;
_fd_bound->value = value;
return true;
}
int _fd_bound_value()
{
assert(_fd_bound != NULL);
return _fd_bound->value;
}
bool _fd_bound_check_set(_fd_store store)
{
int value;
assert(_fd_bound != NULL);
if (!_fd_bound->check(_fd_bound->constraint, store, &value))
return false;
_fd_bound->value = value;
return true;
}
bool _fd_bound_check(_fd_store store)
{
int value;
assert(_fd_bound != NULL);
return _fd_bound->check(_fd_bound->constraint, store, &value) ||
value == _fd_bound->value;
}
int _fd_better_solution(_fd_store s1, _fd_store s2)
{
assert(_fd_bound != NULL);
return _fd_bound->compare(_fd_bound->constraint, s1, s2) < 0;
}
fd_int _fd_bound_variable()
{
assert(_fd_bound != NULL);
return _fd_variables[_fd_bound->variable];
}
/* Bound the optimisation variable and propagate the change. */
int fd__bound_and_revise()
{
assert(_fd_bound != NULL);
if (_fd_bound->bound(_fd_bound->constraint, _fd_bound_value()))
{
if (fd_domain_empty(_fd_bound_variable()))
return FD_NOSOLUTION;
if (_fd_revise_wrt_variable(_fd_bound_variable()) == FD_NOSOLUTION)
{
fd__constraint_data_reset();
return FD_NOSOLUTION;
}
}
return FD_OK;
}