1 package net.obsearch.query;
2 import java.util.List;
3 import java.util.LinkedList;
4 import java.util.HashSet;
5 import java.util.Set;
6 import net.obsearch.ob.OBShort;
7 import net.obsearch.result.OBResultShort;
8 import net.obsearch.result.OBPriorityQueueShort;
9 import net.obsearch.exception.OBException;
10 import net.obsearch.AbstractOBResult;
11 import net.obsearch.asserts.OBAsserts;
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 public final class OBQueryShort<O extends OBShort> extends AbstractOBQuery<O> {
38
39
40 private OBResultShort<O> query;
41
42
43
44 protected OBPriorityQueueShort<O> result;
45
46
47
48
49 protected short[] min;
50
51
52
53
54
55 protected short[] max;
56
57
58
59
60
61
62 protected short[] smap;
63
64
65
66
67 public OBQueryShort(){
68 }
69
70 public O getObject(){
71 return query.getObject();
72 }
73
74
75
76
77
78
79
80
81
82
83 public OBQueryShort(O object, short range, OBPriorityQueueShort<O> result){
84
85 query = new OBResultShort<O>(object,-1,range);
86 this.result = result;
87 }
88
89 public OBQueryShort(O object, OBPriorityQueueShort<O> result){
90 this(object, Short.MAX_VALUE, result);
91 }
92
93
94
95
96
97
98
99
100 public boolean collides(short[][] rectangle){
101 short[] minOther = rectangle[0];
102 short[] maxOther = rectangle[1];
103 boolean res = true;
104 assert minOther.length == smap.length;
105 int i = 0;
106 while (i < minOther.length) {
107 if(max[i] < minOther[i] || min[i] > maxOther[i]){
108 res =false;
109 break;
110 }
111 i++;
112 }
113 return res;
114 }
115
116
117
118
119
120
121
122
123
124
125
126
127 public OBQueryShort(O object, short range, OBPriorityQueueShort<O> result, short[] smap){
128
129 this(object,range,result);
130 this.smap = smap;
131 if(smap != null){
132 min = new short[smap.length];
133 max = new short[smap.length];
134 }
135 updateRectangle();
136
137 }
138
139 private void updateRectangle(){
140 if(smap != null){
141 int i = 0;
142 while (i < smap.length) {
143 min[i] = (short)Math.max(smap[i] - query.getDistance(), 0);
144 max[i] = (short)Math.min(smap[i] + query.getDistance(), Short.MAX_VALUE);
145 i++;
146 }
147 }
148 }
149
150
151
152
153 public short[] getLow(){
154 return min;
155 }
156
157
158
159
160 public short[] getHigh(){
161 return max;
162 }
163
164
165
166
167 public OBPriorityQueueShort<O> getResult(){
168 return result;
169 }
170
171
172
173
174
175
176 public void setResult(OBPriorityQueueShort<O> result){
177 this.result = result;
178 }
179
180
181
182
183
184
185
186 public boolean isCandidate(short smapDistance){
187 return smapDistance <= query.getDistance() && result.isCandidate(smapDistance);
188 }
189
190
191 public boolean add(long id, O object) throws InstantiationException, IllegalAccessException , OBException{
192 return add(id, object, query.getObject().distance(object));
193 }
194
195 public short getDistance(){
196 return query.getDistance();
197 }
198
199 public List<AbstractOBResult<O>> getSortedElements(){
200 List<AbstractOBResult<O>> res = new LinkedList<AbstractOBResult<O>>();
201 for(OBResultShort<O> r : result.getSortedElements()){
202 res.add(r);
203 }
204 return res;
205 }
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222 public boolean add(long id, O obj, short d) throws InstantiationException, IllegalAccessException {
223 if(d <= currentRange()){
224 boolean res = result.add(id,obj,d);
225 short temp = result.updateRange(query.getDistance());
226 if(temp != query.getDistance()){
227 query.setDistance( (short)(temp-(short)1));
228 if(query.getDistance() < 0){
229 query.setDistance( (short)0);
230 }
231
232
233 updateRectangle();
234 }
235 return res;
236 }else{
237 return false;
238 }
239 }
240
241 private short currentRange(){
242 if(result.getSize() == result.getK()){
243
244 return (short)Math.min(query.getDistance(), result.peek().getDistance());
245 }else{
246 return query.getDistance();
247 }
248 }
249
250
251
252
253
254 public boolean updatedRange(short originalRange){
255 return query.getDistance() != originalRange;
256 }
257
258
259
260
261 public boolean isFull(){
262 return result.isFull();
263 }
264
265
266 public double recall(List<AbstractOBResult<O>> perfectQuery){
267 int hits = 0;
268 Set<AbstractOBResult<O>> s = new HashSet<AbstractOBResult<O>>();
269 for(OBResultShort<O> r : this.result.getSortedElements()){
270 int i = 0;
271 for(AbstractOBResult<O> d : perfectQuery){
272 if(! s.contains(d) && d.compareTo(r) == 0){
273 s.add(d);
274 hits++;
275 break;
276 }
277 i++;
278 }
279 }
280 return (double)hits / (double)perfectQuery.size();
281 }
282
283
284 public double ep(List<AbstractOBResult<O>> dbin){
285 List<OBResultShort<O>> query = getResult().getSortedElements();
286 int i = 0;
287 int result = 0;
288 Set<OBResultShort<O>> s = new HashSet<OBResultShort<O>>();
289 for(OBResultShort<O> r : query){
290
291 int cx = 0;
292 for(AbstractOBResult<O> cr : dbin){
293 OBResultShort<O> c = (OBResultShort<O>)cr;
294 if(! s.contains(c) &&c.compareTo(r) == 0){
295 s.add(c);
296 result += cx - i;
297 break;
298 }
299 cx++;
300 }
301 i++;
302 }
303 if(query.size() == 0){
304 return 0;
305 }else{
306 double res = ((double)result)/ ((double)(query.size() * dbin.size()));
307 return res;
308 }
309 }
310
311
312
313
314
315 public double ep(short[] dbin){
316 return epAux(dbin) * (1 / (double)getResult().getSize());
317 }
318
319
320
321
322
323
324
325
326
327 public double approx(short[] dbin) throws OBException {
328
329 List<OBResultShort<O>> query = getResult().getSortedElements();
330
331 if(! this.isFull()){
332 return 1;
333 }
334
335 int last = query.size() - 1;
336 return Math.abs((query.get(last).getDistance()) / dbin[last]);
337 }
338
339
340
341
342
343 private double epAux(short[] dbin){
344 List<OBResultShort<O>> query = getResult().getSortedElements();
345 int i = 0;
346 int result = 0;
347
348 Set<Integer> s = new HashSet<Integer>();
349 for(OBResultShort<O> r : query){
350
351 int cx = 0;
352 for(short cr : dbin){
353 if(! s.contains(cx) && cr == r.getDistance()){
354 s.add(cx);
355 result += cx - i;
356 break;
357 }
358 cx++;
359 }
360 i++;
361 }
362 if(query.size() == 0){
363 return 0;
364 }else{
365 double res = ((double)result)/ ((double)(dbin.length));
366 return res;
367 }
368 }
369
370
371
372
373
374 public double compound(short[] dbin){
375 List<OBResultShort<O>> query = getResult().getSortedElements();
376 int i = 0;
377
378 double res = 0;
379
380 Set<Integer> s = new HashSet<Integer>();
381 for(OBResultShort<O> r : query){
382
383 double ep = 1 - (((double)rank(r.getDistance(), dbin) - (i))/(double)(dbin.length));
384
385 if(r.getDistance() == 0){
386 assert dbin[i] == 0;
387 res += 1;
388 }else{
389 res += ((double)dbin[i] / (double)r.getDistance()) * ep;
390 }
391 i++;
392 }
393 return res / (double) query.size();
394 }
395
396
397
398
399 public double rde(short[] dbin){
400 return rdeAux(dbin) / (double) getResult().getSize();
401 }
402
403
404
405
406 private double rdeAux(short[] dbin){
407 List<OBResultShort<O>> query = getResult().getSortedElements();
408 int i = 0;
409 double result = 0;
410
411 for(OBResultShort<O> r : query){
412
413 if(dbin[i] != 0){
414 result += ( (double) r.getDistance() / (double)dbin[i]) - 1;
415 }
416 i++;
417 }
418 return result;
419 }
420
421
422
423
424
425 public double tDR(short[] dbin){
426 List<OBResultShort<O>> query = getResult().getSortedElements();
427 int i = 0;
428 double up = 0;
429 double down = 0;
430
431 for(OBResultShort<O> r : query){
432
433 up += (double)dbin[i];
434 down += (double) r.getDistance();
435 i++;
436 }
437 return up / down;
438 }
439
440
441
442
443 public double precision(short[] dbin){
444 List<OBResultShort<O>> query = getResult().getSortedElements();
445 int count = 0;
446
447 for(OBResultShort<O> r : query){
448 if(rank(r.getDistance(), dbin) < query.size()) {
449 count++;
450 }
451 }
452 return (double) count / (double) query.size();
453 }
454
455
456
457
458 private int rank(short distance, short[] dbin){
459 int i = 0;
460 while(i < dbin.length){
461 if(distance == dbin[i]){
462 break;
463 }
464 i++;
465 }
466 return i;
467 }
468
469
470
471
472 public short peek() throws OBException{
473 OBAsserts.chkAssert(isFull(), "Queue is not full");
474 return result.peek().getDistance();
475 }
476
477 }
478
479