File: nearest_neighbor_graph_ann.cpp

package info (click to toggle)
graphviz 14.0.5-2
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 139,388 kB
  • sloc: ansic: 141,938; cpp: 11,957; python: 7,766; makefile: 4,043; yacc: 3,030; xml: 2,972; tcl: 2,495; sh: 1,388; objc: 1,159; java: 560; lex: 423; perl: 243; awk: 156; pascal: 139; php: 58; ruby: 49; cs: 31; sed: 1
file content (121 lines) | stat: -rw-r--r-- 3,907 bytes parent folder | download | duplicates (2)
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
/*************************************************************************
 * Copyright (c) 2011 AT&T Intellectual Property
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors: Details at https://graphviz.org
 *************************************************************************/

#include <ANN/ANN.h>					// ANN declarations
#include <mingle/nearest_neighbor_graph_ann.h>
#include <utility>
#include <vector>

static const int dim = 4; // dimension

static void sortPtsX(int n, ANNpointArray pts){
  /* sort so that edges always go from left to right in x-doordinate */
  for (int i = 0; i < n; i++){
    ANNpoint p = pts[i];
    if (p[0] < p[2] || (p[0] == p[2] && p[1] < p[3])) continue;
    std::swap(p[0], p[2]);
    std::swap(p[1], p[3]);
  }
}

static void sortPtsY(int n, ANNpointArray pts){
  /* sort so that edges always go from left to right in x-doordinate */
  for (int i = 0; i < n; i++){
    ANNpoint p = pts[i];
    if (p[1] < p[3] || (p[1] == p[3] && p[0] < p[2])) continue;
    std::swap(p[0], p[2]);
    std::swap(p[1], p[3]);
  }
}

void nearest_neighbor_graph_ann(int nPts, int k, const std::vector<double> &x,
                                int &nz0, std::vector<int> &irn,
                                std::vector<int> &jcn,
                                std::vector<double> &val) {

  /* Gives a nearest neighbor graph is a list of dim-dimendional points. The connectivity is in irn/jcn, and the distance in val.
     
    nPts: number of points
    dim: dimension
    k: number of neighbors needed
    x: nPts*dim vector. The i-th point is x[i*dim : i*dim + dim - 1]
    nz: number of entries in the connectivity matrix irn/jcn/val
    irn, jcn: the connectivity 
    val: the distance

    note that there could be repeates
  */

  // error tolerance
  const double eps = 0;

  ANNpointArray dataPts = annAllocPts(nPts, dim);			// allocate data points
  std::vector<ANNidx> nnIdx(k);						// allocate near neighbor indices
  std::vector<ANNdist> dists(k);					// allocate near neighbor dists

  for (int i = 0; i < nPts; i++){
    double *xx =  dataPts[i];
    for (int j = 0; j < dim; j++) xx[j] = x[i*dim + j];
  }

  //========= graph when sort based on x ========
  int nz = 0;
  sortPtsX(nPts, dataPts);
  ANNkd_tree xTree( // build search structure
			  dataPts,					// the data points
			  nPts,						// number of points
			  dim);						// dimension of space
  for (int ip = 0; ip < nPts; ip++){
    xTree.annkSearch( // search
		       dataPts[ip],						// query point
		       k,								// number of near neighbors
		       nnIdx.data(),						// nearest neighbors (returned)
		       dists.data(),						// distance (returned)
		       eps);							// error bound

    for (int i = 0; i < k; i++) {			// print summary
      if (nnIdx[i] == ip) continue;
      val[nz] = dists[i];
      irn[nz] = ip;
      jcn[nz++] = nnIdx[i];
    }
  }
  

  //========= graph when sort based on y ========
  sortPtsY(nPts, dataPts);
  ANNkd_tree yTree( // build search structure
			  dataPts,					// the data points
			  nPts,						// number of points
			  dim);						// dimension of space
  for (int ip = 0; ip < nPts; ip++){
    yTree.annkSearch( // search
		       dataPts[ip],						// query point
		       k,								// number of near neighbors
		       nnIdx.data(),						// nearest neighbors (returned)
		       dists.data(),						// distance (returned)
		       eps);							// error bound
      
    for (int i = 0; i < k; i++) {			// print summary
      if (nnIdx[i] == ip) continue;
      val[nz] = dists[i];
      irn[nz] = ip;
      jcn[nz++] = nnIdx[i];
    }
  }
    
  nz0 = nz;

  annDeallocPts(dataPts);
  annClose();									// done with ANN



}