Cyclops Tensor Framework
parallel arithmetic on multidimensional arrays
mis.cxx
Go to the documentation of this file.
1 
7 #include <ctf.hpp>
8 using namespace CTF;
9 
16  assert(undir_A.symm == SH);
17 
18  int n = undir_A.nrow;
19 
20  //extract lower triangular part of undir_A into nonsymmetric matrix
21  //gives a directed adjacency matrix A
22  int nosym[] = {NS, NS};
23  Tensor<float> A(undir_A,nosym);
24 
25  //vector of removed vertices
26  Vector<float> r(n);
27 
28  //vector of MIS vertices
29  Vector<float> s(n,SP);
30 
31  for (;;){
32  //find all roots of remainder graph
33  Vector<float> v(n);
34  //let v be 1 for all non-removed vertices
35  v["i"] = 1.;
36  v["i"] -= r["i"];
37  v.sparsify([](float f){ return f==1.0; });
38 
39  //if there are no such vertices we are done
40  if (v.nnz_tot == 0) return s;
41 
42  //find everything connected to non-removed vertices
43  v["i"] += A["ij"]*v["j"];
44 
45  //filter down to non-removed vertices that have no incoming
46  //edges from non-removed vertices (are roots in remainder graph)
47  v["i"] += (1.+n)*r["i"];
48  v.sparsify([](float f){ return f==1.0; });
49 
50  //add these to MIS
51  s["i"] += v["i"];
52 
53  //find all decendants of MIS vertices
54  v["i"] += A["ij"]*v["j"];
55 
56  //tag these vertices for removal
57  r["i"] += v["i"];
58 
59  /*Transform<float,float>(
60  [](float w, float & a){ if (w != 0.) a = 0; }
61  )(w["i"], A["ij"]);
62  Transform<float,float>(
63  [](float w, float & a){ if (w != 0.) a = 0; }
64  )(w["i"], A["ji"]);*/
65  }
66 }
67 
68 bool test_mis(int n, double sp_frac){
69  //create random graph with sp_frac*n*(n-1)/2 nonzeros
70  Matrix<float> A(n,n,SH|SP);
71  srand48(A.wrld->rank);
72  A.fill_sp_random(1.0,1.0,sp_frac);
73 
74  //compute MIS of A
75  Vector<float> s = mis(A);
76  if (A.wrld->rank == 0){
77  printf("Found MIS of size %ld\n",s.nnz_tot);
78  }
79  Vector<float> t(n);
80 
81  //find all neighbors of MIS
82  t["i"] += A["ij"]*s["j"];
83 
84  //if MIS is independent t should be zero everywhere s isn't
85  float zero = s["i"]*t["i"];
86 
87  if (zero != 0.0){
88  if (A.wrld->rank == 0){
89  printf("Falure: MIS is not independent!\n");
90  }
91  return false;
92  }
93  //if MIS is maximal, s+t should be nonzero everywhere
94  t["i"] += s["i"];
96  scl[""] = Function<float,int>([](float a){ return (int)(a == 0.); })(t["i"]);
97  int nnz = scl.get_val();
98  if (nnz != 0){
99  if (A.wrld->rank == 0){
100  printf("Falure: MIS is not maximal, nnz = %d!\n",nnz);
101  }
102  return false;
103  }
104  return true;
105 
106 }
107 
108 
109 #ifndef TEST_SUITE
110 char* getCmdOption(char ** begin,
111  char ** end,
112  const std::string & option){
113  char ** itr = std::find(begin, end, option);
114  if (itr != end && ++itr != end){
115  return *itr;
116  }
117  return 0;
118 }
119 
120 
121 int main(int argc, char ** argv){
122  int rank, np, pass, n;
123  float sp_frac;
124  int const in_num = argc;
125  char ** input_str = argv;
126 
127  MPI_Init(&argc, &argv);
128  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
129  MPI_Comm_size(MPI_COMM_WORLD, &np);
130 
131  if (getCmdOption(input_str, input_str+in_num, "-n")){
132  n = atoi(getCmdOption(input_str, input_str+in_num, "-n"));
133  if (n < 0) n = 16;
134  } else n = 16;
135 
136  if (getCmdOption(input_str, input_str+in_num, "-sp_frac")){
137  sp_frac = atof(getCmdOption(input_str, input_str+in_num, "-sp_frac"));
138  if (sp_frac < 0) sp_frac = .1;
139  } else sp_frac = .1;
140 
141  {
142  World dw(argc, argv);
143 
144  if (rank == 0){
145  printf("Running MIS with n=%d, sp_frac=%lf\n",n,sp_frac);
146  }
147  pass = test_mis(n,sp_frac);
148  if (rank == 0){
149  if (pass)
150  printf("MIS passed.\n");
151  else
152  printf("MIS FAILED.\n");
153  }
154  }
155 
156  MPI_Finalize();
157  return 0;
158 }
164 #endif
Matrix class which encapsulates a 2D tensor.
Definition: matrix.h:18
def rank(self)
Definition: core.pyx:312
Definition: common.h:37
dtype get_val()
returns scalar value
bool test_mis(int n, double sp_frac)
Definition: mis.cxx:68
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
string
Definition: core.pyx:456
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
void sparsify()
reduce tensor to sparse format, storing only nonzero data, or data above a specified threshold...
Definition: tensor.cxx:449
Vector< float > mis(Matrix< float > &undir_A)
Definition: mis.cxx:15
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: mis.cxx:110
int main(int argc, char **argv)
Definition: mis.cxx:121
Definition: common.h:37
def np(self)
Definition: core.pyx:315