parExQHV
Compute Exclusive HyperVolumes using threads
 All Data Structures Files Functions Variables Macros
quickhvolume.c
1 /*
2  *
3  * Copyright (c) Year(s), 2013, Luis M. S. Russo and Alexandre
4  * P. Francisco / KDBIO / INESC-ID, <qhv@kdbio.inesc-id.pt>
5  *
6  * Any published media that is related with to use of the distributed
7  * software, or derived software, must contain a reference to "Extending
8  * quick hypervolume. Luís M. S. Russo, Alexandre P. Francisco:
9  * J. Heuristics 22(3): 245-271 (2016)".
10  *
11  * Permission to use, copy, modify, and/or distribute this software for
12  * any purpose with or without fee is hereby granted, provided that the
13  * above copyright notice and this permission notice appear in all
14  * copies.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
17  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
19  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
20  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
21  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23  * PERFORMANCE OF THIS SOFTWARE.
24  *
25  */
26 
27 #include <pthread.h>
28 #include <stdio.h>
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <float.h>
33 #include <strings.h>
34 #include <sys/types.h> /* basic system data types */
35 #include <limits.h> /* PIPE_BUF */
36 #include "unionFilter.h"
37 #include "quickhvolume.h"
38 #include "constants.h"
39 #include "HSO.h"
40 #include "subsets.h"
41 #include "division.h"
42 #include "splitter.h"
43 #include "macros.h"
44 #include "inexclusion.h"
45 #include "tpool.h"
46 
47 
48 void openBox(toolBox* b)
49 {
50 #warning TODO: There should be a better solution to the initUnion problem.
51 
52  b->spt.uD.size = 0; /* This was hidden in a static variable. */
53  initUnion(NPOINTS, &(b->spt.uD));
55  initSplitter(&(b->spt));
56 }
57 
58 void closeBox(toolBox* b)
59 {
60  destroySplitter(&(b->spt));
61 }
62 
63 int priority(taskData* d)
64 {
65  return d->n;
66 }
67 
68 void jobCopy(jobData* dst, jobData* src)
69 {
70  int i;
71 
72  dst->n = src->n;
73  memcpy(&(dst->PS[0]), &(src->PS[0]), (src->n)*sizeof(point));
74 
75  i = 0;
76  while(i < src->n)
77  {
78  dst->r[i] = 0;
79  i++;
80  }
81 }
82 
83 void taskCopy(taskData* dst, taskData* src)
84 {
85  int i;
86 
87  memcpy(dst, src, offsetof(struct taskData, idx));
88  memcpy(&(dst->idx[0]), &(src->idx[0]), (src->n)*sizeof(int));
89 
90  i = 0;
91  while(i < src->n)
92  {
93  dst->r[i] = 0;
94  i++;
95  }
96 }
97 
98 void merge(jobData* dst, taskData* src)
99 {
100  int i;
101 
102  i = 0;
103  while(i < src->n)
104  {
105  dst->r[src->idx[i]] += src->r[i];
106  i++;
107  }
108 }
109 
110 void publish(int jid, jobData* jd)
111 {
112  int i;
113 
114  i = 0;
115  while(i < jd->n)
116  {
117  printf("Ex[%d] = %1.10f\t", i, jd->r[i]);
118  i++;
119  }
120  printf("\n");
121 }
122 
123 /* global variables */
124 
125 /* file scope macro definitions */
126 
127 /* file scope type declarations */
128 
129 /* file scope variables */
130 
131 /* file scope functions declarations */
132 
133 static void quickHVolumeR(toolBox* b, taskData* d, const jobData* jd);
134 
143 static void drop(int* idx, int* n, int j);
144 
150 static sureInline(void) swapD(double* r, int n, int j);
151 
152 /* file scope functions */
153 
154 static sureInline(void) swapD(double* r, int n, int j)
155 {
156  double t;
157 
158  t = r[n];
159  r[n] = r[j];
160  r[j] = t;
161 }
162 
163 static void drop(int* idx, int* n, int j)
164 {
165  (*n)--;
166  idx[j] = idx[*n];
167 }
168 
169 void quickHVolumeS(toolBox* b, taskData* d, const jobData* jd)
170 {
171  point p;
172  point pp;
173  double tp[3];
175  if(d->n < N)
176  /* if(1 == d->n) */
177  {
178  switch(d->n)
179  {
180  case 1:
181  intercept(&p, &(d->o), &(jd->PS[d->idx[0]]));
182  d->r[0] += HV(&(d->z), &p);
183  break;
184  case 2:
185  intercept(&p, &(d->o), &(jd->PS[d->idx[0]]));
186  tp[0] = HV(&(d->z), &p);
187 
188  intercept(&pp, &(d->o), &(jd->PS[d->idx[1]]));
189  tp[1] = HV(&(d->z), &pp);
190 
191  intercept(&p, &p, &pp);
192  tp[2] = HV(&(d->z), &p);
193 
194  d->r[0] += tp[0] - tp[2];
195  d->r[1] += tp[1] - tp[2];
196  break;
197 
198  default:
199  exInExClusion(&(d->z), &(d->o), d->n, d->idx, jd->PS, d->r, &(b->iex));
200  break;
201  }
202  }
203  else
204  {
205  quickHVolumeR(b, d, jd);
206  }
207 }
208 
209 /* paper: 1 */
210 static void quickHVolumeR(toolBox* b, taskData* d, const jobData* jd)
211 {
212  double hv;
213  division di;
214  int i, j, k;
215  point p;
216  point pp;
217  point ppp;
218  double max;
219  int* nidx;
221  taskData ld;
222  int lidx[NPOINTS];
224  point* A[3];
226 
228  k = 0;
229  A[0] = &(d->o);
230  A[1] = &ppp;
231  A[2] = &p;
232  while(k < 2)
233  {
234  max = -DBL_MAX;
235  i = k;
236  while(i < d->n)
237  {
238  intercept(&pp, &(d->o), &(jd->PS[d->idx[i]]));
239  hv = objective(&(d->z), &pp, &(d->o));
240  if(hv > max)
241  {
242  max = hv;
243  j = i;
244  }
245  i++;
246  }
247  intercept(A[k+1], A[k], &(jd->PS[d->idx[j]]));
248  swap(d->idx, k, j);
250  swapD(d->r, k, j);
252  k++;
253  }
254 
255  /* d->r += HV(&(d->z), &p); */
256 
258  i = 0;
259  while(i < d->n)
260  {
261  intercept(&pp, &(d->o), &(jd->PS[d->idx[i]]));
262  push(d->idx[i], classify(&p, &pp), &(b->spt));
263  i++;
264  }
265  di = newDivision(&(jd->PS[0]), &(d->o), &p, &(b->spt));
266 
267  ld.o = d->o;
268  ld.z = d->z;
269  ld.n = d->n;
270  memcpy(ld.idx, d->idx, (d->n)*sizeof(int));
271  memcpy(ld.r, d->r, (d->n)*sizeof(double));
272 
273  i = 0;
274  while(i < d->n)
275  {
276  lidx[d->idx[i]] = i;
277  i++;
279  }
280 
282  while(hasNext(di))
283  {
284  nidx = next(di, &j, &(d->n));
285  memcpy(d->idx, nidx, (d->n)*sizeof(int));
286  projectZero(&(d->z), &p, j, &(ld.z));
287  projectOne(&(d->o), &p, j, &(ld.o));
288  memset(d->r, 0, sizeof(double)*d->n);
289 
290  prun(d, d->n >= N);
291 
292  i = 0;
293  while(i < d->n)
294  {
295  ld.r[lidx[d->idx[i]]] += d->r[i];
296  i++;
297  }
298 #warning DONE. Regrouping is OK.
299  }
300  freeDivision(&di);
301 
302  d->o = ld.o;
303  d->z = ld.z;
304  d->n = ld.n;
305  memcpy(d->idx, ld.idx, (d->n)*sizeof(int));
306  memcpy(d->r, ld.r, (d->n)*sizeof(double));
307 }
308 /* paper: 0 */
309 
310 /* public functions */
311 
312 /* ------------------------------------------------------ */
#define objective(Z, A, O)
Definition: point.h:84
void freeDivision(division *d)
New divisions are created in the splitter object.
Definition: division.c:53
int * next(division d, int *hypoct, int *n)
Definition: division.c:68
division newDivision(point *PS, point *o, point *p, struct spData *sd)
Definition: splitter.c:129
This returns iterators for diferent type. WARNING, these objects are singleton, so new overwrites exi...
int idx[NPOINTS]
Definition: tdata.h:85
void initUnion(int n, struct unionData *ud)
Definition: unionFilter.c:49
This struct is public because of splitter. Do not use direct access.
Definition: tdata.h:48
void initSplitter(struct spData *sd)
Definition: splitter.c:78
Definition: tdata.h:80
void push(int idx, int tp, struct spData *sd)
Definition: splitter.c:114
A splitter for storing classified points. The splitter is an array that grows dinamically, when all points are inserted they are separeted into classes by sorting. Preferably count sort or hased count sort.
Structure for uniting two sets, without repetition.
double r[NPOINTS]
Definition: tdata.h:76
Inclusion Exclusion Algorithm better than HSO for high d and small n.
Point is an array of coordinates, in a struct for simple and fast copy.
Definition: pointStruct.h:47
int hasNext(division d)
Definition: division.c:63
Definition: tdata.h:72
void destroySplitter(struct spData *sd)
Definition: splitter.c:95
double exInExClusion(point *zero, point *one, int n, int *idx, point *PS, double *exHV, struct iex *ax)
Definition: inexclusion.c:185
Header: copy HSO.