Cyclops Tensor Framework
parallel arithmetic on multidimensional arrays
mis2.cxx
Go to the documentation of this file.
1 
7 #include <ctf.hpp>
8 #include <float.h>
9 using namespace CTF;
10 
17  assert(undir_A.symm == SH);
18  World dw(MPI_COMM_WORLD);
19  int n = undir_A.nrow;
20 
21  //extract lower triangular part of undir_A into nonsymmetric matrix
22  //gives a directed adjacency matrix A
23  int nosym[] = {NS, NS};
24  Tensor<float> A(undir_A,nosym);
25 
26  //vector of removed vertices
27  Vector<float> r(n);
28 
29  //vector of MIS vertices
30  Vector<float> s(n,SP);
31 
32  //vector [1,2,3,...,n]
33  Vector<float> inds(n);
34  Pair<float> * prs;
35  int64_t nloc;
36  inds.get_local_pairs(&nloc, &prs);
37  for (int i=0; i<nloc; i++){
38  prs[i].d = prs[i].k+1.;
39  }
40  inds.write(nloc,prs);
41  delete [] prs;
42 
43  Semiring<float> max_semiring(0., [](float a, float b){ return std::max(a,b); }, MPI_MAX,
44  1.0, [](float a, float b){ return a*b; });
45  int nrecurs = 0;
46  for (;;){
47  //find all roots of remainder graph
48  Vector<float> v(n);
49  //let v be 1 for all non-removed vertices
50  v["i"] = 1.;
51  v["i"] -= r["i"];
52  v.sparsify([](float f){ return f==1.0; });
53  nrecurs++;
54  //if there are no such vertices we are done
55  if (v.nnz_tot == 0) break;
56 
57  //find everything connected to non-removed vertices
58  v["i"] += A["ij"]*v["j"];
59 
60  //filter down to non-removed vertices that have no incoming
61  //edges from non-removed vertices (are roots in remainder graph)
62  v["i"] += (1.+n)*r["i"];
63  v.sparsify([](float f){ return f==1.0; });
64  //define vector for which additions means max
65  Vector<float> w(n,SP,dw,max_semiring);
66  //set values of v to be the corresponding vectors indices
67  Transform<float,float>([](float a, float & b){ b=a; })(inds["i"],v["i"]);
68 
69  //find everything connected to the roots, recording the max root index connected to each vertex
70  w["i"] += undir_A["ij"]*v["j"];
71 
72  //propagate back the maxs, recording the max label of any vertex connected to a root
73  Vector<float> z(n,SP,dw,max_semiring);
74  z["i"] += undir_A["ji"]*w["j"];
75 
76  //add 1 to all nonzeros in v
77  Transform<float>([](float & a){ a+=1; })(v["i"]);
78 
79  //subtract out the max labels, yielding 1. for each root that has a minimal index among roots in 2-neighborhood
80  v["i"] += -1.0*z["i"];
81  //keep only roots that are minimal
82  v.sparsify([](float a){ return a > 0.9; });
83 
84  //add these to the 2-MIS
85  s["i"] += v["i"];
86 
87  //find everything two hops away from the new roots
88  v["i"] += undir_A["ij"]*v["j"];
89  v["i"] += undir_A["ij"]*v["j"];
90 
91  //label all of that for removal
92  r["i"] += v["i"];
93  }
94  if (undir_A.wrld->rank == 0) printf("took %d recursive steps\n",nrecurs);
95  Transform<float>([](float & a){ a=1.; })(s["i"]);
96  return s;
97 }
98 
99 bool test_mis2(int n, double sp_frac){
100  //create random graph with sp_frac*n*(n-1)/2 nonzeros
101  Matrix<float> A(n,n,SH|SP);
102  srand48(A.wrld->rank);
103  A.fill_sp_random(1.0,1.0,sp_frac);
104 
105  //compute 2-MIS of A
106  Vector<float> s = mis2(A);
107  if (A.wrld->rank == 0){
108  printf("Found 2-MIS of size %ld\n",s.nnz_tot);
109  }
110 
111  //create copy of 2-MIS
112  Vector<float> t(s);
113 
114  //add to copy of 2-MIS all neighbors of 2-MIS
115  t["i"] += A["ij"]*s["j"];
116  //if 2-MIS is correct t should be 1 everywhere
117 
119  scl[""] = Function<float,int>([](float a){ return (int)(a > 1.1); })(t["i"]);
120  int nnz = scl.get_val();
121  if (nnz != 0){
122  if (A.wrld->rank == 0){
123  printf("Falure: 2-MIS is not 2-independent, nnz = %d!\n",nnz);
124  }
125  return false;
126  }
127  scl[""] = Function<float,int>([](float a){ return (int)(a < .9); })(t["i"]);
128  nnz = scl.get_val();
129  if (nnz != 0){
130  if (A.wrld->rank == 0){
131  printf("Falure: 2-MIS is not maximal, nnz = %d!\n",nnz);
132  }
133  return false;
134  }
135  return true;
136 
137 }
138 
139 
140 #ifndef TEST_SUITE
141 char* getCmdOption(char ** begin,
142  char ** end,
143  const std::string & option){
144  char ** itr = std::find(begin, end, option);
145  if (itr != end && ++itr != end){
146  return *itr;
147  }
148  return 0;
149 }
150 
151 
152 int main(int argc, char ** argv){
153  int rank, np, pass, n;
154  float sp_frac;
155  int const in_num = argc;
156  char ** input_str = argv;
157 
158  MPI_Init(&argc, &argv);
159  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
160  MPI_Comm_size(MPI_COMM_WORLD, &np);
161 
162  if (getCmdOption(input_str, input_str+in_num, "-n")){
163  n = atoi(getCmdOption(input_str, input_str+in_num, "-n"));
164  if (n < 0) n = 16;
165  } else n = 16;
166 
167  if (getCmdOption(input_str, input_str+in_num, "-sp_frac")){
168  sp_frac = atof(getCmdOption(input_str, input_str+in_num, "-sp_frac"));
169  if (sp_frac < 0) sp_frac = .1;
170  } else sp_frac = .1;
171 
172  {
173  World dw(argc, argv);
174 
175  if (rank == 0){
176  printf("Running 2-MIS with n=%d, sp_frac=%lf\n",n,sp_frac);
177  }
178  pass = test_mis2(n,sp_frac);
179  if (rank == 0){
180  if (pass)
181  printf("2-MIS passed.\n");
182  else
183  printf("2-MIS FAILED.\n");
184  }
185  }
186 
187  MPI_Finalize();
188  return 0;
189 }
195 #endif
dtype d
tensor value associated with index
Definition: tensor.h:34
bool test_mis2(int n, double sp_frac)
Definition: mis2.cxx:99
Matrix class which encapsulates a 2D tensor.
Definition: matrix.h:18
void get_local_pairs(int64_t *npair, Pair< dtype > **pairs, bool nonzeros_only=false, bool unpack_sym=false) const
gives the global indices and values associated with the local data
Definition: tensor.cxx:201
def rank(self)
Definition: core.pyx:312
Definition: common.h:37
dtype get_val()
returns scalar value
Semiring is a Monoid with an addition multiplicaton function addition must have an identity and be as...
Definition: semiring.h:359
Vector class which encapsulates a 1D tensor.
Definition: vector.h:14
Definition: common.h:37
int symm
Definition: matrix.h:20
an instance of the CTF library (world) on a MPI communicator
Definition: world.h:19
int64_t k
key, global index [i1,i2,...] specified as i1+len[0]*i2+...
Definition: tensor.h:31
string
Definition: core.pyx:456
int main(int argc, char **argv)
Definition: mis2.cxx:152
index-value pair used for tensor data input
Definition: tensor.h:28
CTF::World * wrld
distributed processor context on which tensor is defined
def scl(self, s)
Definition: core.pyx:473
Scalar class which encapsulates a 0D tensor.
Definition: scalar.h:13
int rank
rank of local processor
Definition: world.h:24
Vector< float > mis2(Matrix< float > &undir_A)
Definition: mis2.cxx:16
void sparsify()
reduce tensor to sparse format, storing only nonzero data, or data above a specified threshold...
Definition: tensor.cxx:449
int64_t nnz_tot
maximum number of local nonzero elements over all procs
void fill_sp_random(dtype rmin, dtype rmax, double frac_sp)
generate roughly frac_sp*dense_tensor_size nonzeros between rmin and rmax, works only for dtype in {f...
Definition: tensor.cxx:969
int nrow
Definition: matrix.h:20
Definition: apsp.cxx:17
an instance of a tensor within a CTF world
Definition: tensor.h:74
char * getCmdOption(char **begin, char **end, const std::string &option)
Definition: mis2.cxx:141
void write(int64_t npair, int64_t const *global_idx, dtype const *data)
writes in values associated with any set of indices The sparse data is defined in coordinate format...
Definition: tensor.cxx:264
Definition: common.h:37
def np(self)
Definition: core.pyx:315