RaySolving.cxx
Go to the documentation of this file.
2 #include "WireCellUtil/Ress.h"
3 
4 using namespace WireCell;
5 
7 {
8  auto it = m_wid2vtx.find(wid);
9  if (it != m_wid2vtx.end()) {
10  return it->second;
11  }
12  vertex_t node = boost::add_vertex(m_graph);
13  m_wid2vtx[wid] = node;
14  m_graph[node].ntype = 'w';
15  m_graph[node].ident = wid;
16  m_graph[node].value = 0.0;
17  m_graph[node].weight = 1.0;
18  return node;
19 }
20 
21 void RayGrid::Grouping::add(char ntype, ident_t chid, std::vector<ident_t> wids, float value, float weight)
22 {
23  vertex_t node = boost::add_vertex(m_graph);
24  m_graph[node].ntype = ntype;
25  m_graph[node].ident = chid;
26  m_graph[node].value = value;
27  m_graph[node].weight = weight;
28 
29  for (const auto wid : wids) {
30  auto wnode = wire_node(wid);
31  boost::add_edge(node, wnode, m_graph);
32  }
33 }
34 
35 
37 {
38  clusterset_t ret;
39 
40  std::unordered_map<vertex_t, int> stripes;
41  int nstripes = boost::connected_components(m_graph, boost::make_assoc_property_map(stripes));
42  if (!nstripes) {
43  return ret;
44  }
45 
46  for (auto& vci : stripes) {
47  vertex_t vtx = vci.first;
48  char ntype = m_graph[vtx].ntype;
49  if (ntype == 'w') {
50  continue;
51  }
52  const size_t stripe_index = vci.second;
53  ret[stripe_index].push_back(m_graph[vtx]);
54  }
55  return ret;
56 }
57 
58 //
59 // Solving
60 //
61 
62 
64 {
65  auto it = m_sid2vtx.find(sid);
66  if (it != m_sid2vtx.end()) {
67  return it->second;
68  }
69  vertex_t snode = boost::add_vertex(m_graph);
70  m_sid2vtx[sid] = snode;
71  m_graph[snode].ntype = 's';
72  m_graph[snode].ident = sid;
73  m_graph[snode].value = value;
74  m_graph[snode].weight = weight;
75  return snode;
76 }
77 
79 {
80  vertex_t mnode = boost::add_vertex(m_graph);
81  m_graph[mnode].ntype = 'm';
82  m_graph[mnode].ident = 0xdeadbeef;
83  m_graph[mnode].value = value;
84  m_graph[mnode].weight = weight;
85  return mnode;
86 }
87 
89 {
90  for (const auto& it : cset) {
91  double total_value = 0;
92  double total_weight = 0;
93  int nms = 0;
94  std::vector<vertex_t> snodes;
95  for (const auto& node : it.second) {
96  if (node.ntype == 'm') {
97  total_value += node.value;
98  total_weight += node.weight;
99  ++nms;
100  continue;
101  }
102  if (node.ntype == 's') {
103  auto snode = source_node(node.ident, node.value, node.weight);
104  snodes.push_back(snode);
105  continue;
106  }
107  // skip w's
108  }
109  if (!nms or snodes.empty()) {
110  // require at least one measurement and one source.
111  continue;
112  }
113  auto mnode = measurement_node(total_value, total_weight/nms);
114  for (auto snode : snodes) {
115  boost::add_edge(mnode, snode, m_graph);
116  }
117  }
118 }
119 
120 
122  const std::vector<vertex_t>& sources,
123  const std::vector<vertex_t>& measures)
124 {
125  // convert source nodes and their edge end mnodes to m vector and G matrix
126  Ress::vector_t meas = Ress::vector_t::Zero(measures.size());
127  Ress::vector_t init = Ress::vector_t::Zero(sources.size());
128  Ress::vector_t weight = Ress::vector_t::Zero(sources.size());
129  Ress::matrix_t geom = Ress::matrix_t::Zero(measures.size(), sources.size());
130  std::unordered_map<vertex_t, size_t> sv2ind, mv2ind;
131  for (size_t mind=0; mind<measures.size(); ++mind) {
132  vertex_t mvtx = measures[mind];
133  mv2ind[mvtx] = mind;
134  meas(mind) = m_graph[mvtx].value;
135  }
136  for (size_t sind=0; sind<sources.size(); ++sind) {
137  vertex_t svtx = sources[sind];
138  sv2ind[svtx] = sind;
139  init(sind) = m_graph[svtx].value;
140  weight(sind) = m_graph[svtx].weight;
141  auto medges = boost::out_edges(svtx, m_graph);
142  for (auto mit = medges.first; mit != medges.second; ++mit) {
143  auto mvtx = target(*mit, m_graph);
144  size_t mind = mv2ind[mvtx];
145  geom(mind, sind) = 1.0;
146  }
147  // fixme: this ignores measurement weights.
148  }
149 
150  Ress::Params params;
151  params.model = Ress::lasso;
152  Ress::vector_t solved = Ress::solve(geom, meas, params, init, weight);
153  for (int sind = 0; sind < solved.size(); ++sind) {
154  auto svtx = sources[sind];
155  m_graph[svtx].value = solved[sind];
156  answer[m_graph[svtx].ident] = solved[sind];
157  }
158 }
159 
162 {
163  std::unordered_map<vertex_t, int> probs;
164  int nprobs = boost::connected_components(m_graph, boost::make_assoc_property_map(probs));
165 
166 
167  solution_t answer;
168  if (!nprobs) {
169  return answer;
170  }
171 
172  struct SMVecs {
173  std::vector<vertex_t> sources, measures;
174  };
175  std::unordered_map<int, SMVecs> smvecs;
176  for (auto it : probs) {
177  auto vtx = it.first;
178  if (m_graph[vtx].ntype == 's') {
179  smvecs[it.second].sources.push_back(vtx);
180  }
181  if (m_graph[vtx].ntype == 'm') {
182  smvecs[it.second].measures.push_back(vtx);
183  }
184  }
185 
186  for (auto sit : smvecs) {
187  solve_one(answer, sit.second.sources, sit.second.measures);
188  }
189  return answer;
190 
191 }
std::unordered_map< ident_t, vertex_t > m_wid2vtx
Definition: RaySolving.h:50
vector_t solve(matrix_t response, vector_t measured, const Params &params=Params(), vector_t source=Eigen::VectorXd(), vector_t weights=Eigen::VectorXd())
Definition: Ress.cxx:7
Eigen::VectorXd vector_t
Definition: Ress.h:12
std::unordered_map< int, cluster_t > clusterset_t
Definition: RaySolving.h:41
init
Definition: train.py:42
boost::graph_traits< graph_t >::vertex_descriptor vertex_t
Definition: RaySolving.h:72
vertex_t source_node(ident_t sid, float value, float weight)
Definition: RaySolving.cxx:63
vertex_t wire_node(ident_t wid)
Definition: RaySolving.cxx:6
boost::graph_traits< graph_t >::vertex_descriptor vertex_t
Definition: RaySolving.h:34
Eigen::MatrixXd matrix_t
Definition: Ress.h:13
virtual void add(char ntype, ident_t chid, std::vector< ident_t > wids, float value, float weight=1.0)
Definition: RaySolving.cxx:21
Definition: Main.h:22
vertex_t measurement_node(float value, float weight)
Definition: RaySolving.cxx:78
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
void solve_one(solution_t &answer, const std::vector< vertex_t > &sources, const std::vector< vertex_t > &measures)
Definition: RaySolving.cxx:121
std::unordered_map< ident_t, float > solution_t
Definition: RaySolving.h:78
weight
Definition: test.py:257
void add(const Grouping::clusterset_t &cset)
Definition: RaySolving.cxx:88
tbb::flow::source_node< boost::any > source_node