Cosmetics.
[mtp.git] / tracker.cc
1
2 ///////////////////////////////////////////////////////////////////////////
3 // This program is free software: you can redistribute it and/or modify  //
4 // it under the terms of the version 3 of the GNU General Public License //
5 // as published by the Free Software Foundation.                         //
6 //                                                                       //
7 // This program is distributed in the hope that it will be useful, but   //
8 // WITHOUT ANY WARRANTY; without even the implied warranty of            //
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      //
10 // General Public License for more details.                              //
11 //                                                                       //
12 // You should have received a copy of the GNU General Public License     //
13 // along with this program. If not, see <http://www.gnu.org/licenses/>.  //
14 //                                                                       //
15 // Written by and Copyright (C) Francois Fleuret                         //
16 // Contact <francois.fleuret@idiap.ch> for comments & bug reports        //
17 ///////////////////////////////////////////////////////////////////////////
18
19 #include "tracker.h"
20
21 #include <iostream>
22
23 using namespace std;
24
25 Tracker::Tracker(int nb_time_steps, int nb_locations) {
26   _nb_locations = nb_locations;
27   _nb_time_steps = nb_time_steps;
28   _detection_score = allocate_array<scalar_t>(_nb_time_steps, _nb_locations);
29   _allowed_motion = allocate_array<int>(_nb_locations, _nb_locations);
30   _entrances = new int[_nb_locations];
31   _exits = new int[_nb_locations];
32
33   for(int l = 0; l < nb_locations; l++) {
34     _entrances[l] = 0;
35     _exits[l] = 0;
36     for(int m = 0; m < nb_locations; m++) {
37       _allowed_motion[l][m] = 0;
38     }
39   }
40
41   _edge_lengths = 0;
42   _graph = 0;
43 }
44
45 Tracker::~Tracker() {
46   delete[] _edge_lengths;
47   delete _graph;
48   deallocate_array<scalar_t>(_detection_score);
49   deallocate_array<int>(_allowed_motion);
50   delete[] _exits;
51   delete[] _entrances;
52 }
53
54 void Tracker::set_allowed_motion(int from_location, int to_location, int v) {
55   _allowed_motion[from_location][to_location] = v;
56 }
57
58 void Tracker::set_as_entrance(int location, int v) {
59   _entrances[location] = v;
60 }
61
62 void Tracker::set_as_exit(int location, int v) {
63   _exits[location] = v;
64 }
65
66 void Tracker::set_detection_score(int time, int location, scalar_t score) {
67   _detection_score[time][location] = score;
68 }
69
70 void Tracker::build_graph() {
71   // Delete existing graph
72   delete[] _edge_lengths;
73   delete _graph;
74
75   int nb_motions = 0, nb_exits = 0, nb_entrances = 0;
76   for(int l = 0; l < _nb_locations; l++) {
77     if(_exits[l]) nb_exits++;
78     if(_entrances[l]) nb_entrances++;
79     for(int m = 0; m < _nb_locations; m++) {
80       if(_allowed_motion[l][m]) nb_motions++;
81     }
82   }
83
84   int nb_vertices = 2 + 2 * _nb_time_steps * _nb_locations;
85
86   int nb_edges =
87     _nb_locations * 2 +
88     (_nb_time_steps - 2) * (nb_exits + nb_entrances) +
89     (_nb_time_steps - 1) * nb_motions +
90     _nb_locations * _nb_time_steps;
91
92   int source = 0, sink = nb_vertices - 1;
93   int *node_from = new int[nb_edges];
94   int *node_to = new int[nb_edges];
95   int e = 0;
96
97   _edge_lengths = new scalar_t[nb_edges];
98
99   // We put the in-node edges first, since these are the ones whose
100   // lengths we will have to change according to the detection score
101
102   for(int t = 0; t < _nb_time_steps; t++) {
103     for(int l = 0; l < _nb_locations; l++) {
104       node_from[e] = 1 + (2 * (t + 0) + 0) * _nb_locations + l;
105       node_to[e] =   1 + (2 * (t + 0) + 1) * _nb_locations + l;
106       e++;
107     }
108   }
109
110   // We put the other edges after
111   for(int l = 0; l < _nb_locations; l++) {
112     node_from[e] = source;
113     node_to[e] = 1 + l + 0 * _nb_locations;
114     _edge_lengths[e] = 0.0;
115     e++;
116   }
117
118   for(int t = 0; t < _nb_time_steps; t++) {
119     for(int l = 0; l < _nb_locations; l++) {
120       if(t == _nb_time_steps - 1) {
121         node_from[e] = 1 + (2 * (t + 0) + 1) * _nb_locations + l;
122         node_to[e] = sink;
123         _edge_lengths[e] = 0.0;
124         e++;
125       } else {
126         for(int k = 0; k < _nb_locations; k++) {
127           if(_allowed_motion[l][k]) {
128             node_from[e] = 1 + (2 * (t + 0) + 1) * _nb_locations + l;
129             node_to[e] =   1 + (2 * (t + 1) + 0) * _nb_locations + k;
130             _edge_lengths[e] = 0.0;
131             e++;
132           }
133         }
134       }
135     }
136   }
137
138   for(int t = 1; t < _nb_time_steps-1; t++) {
139     for(int l = 0; l < _nb_locations; l++) {
140       if(_entrances[l]) {
141         node_from[e] = source;
142         node_to[e] =   1 + (2 * (t + 0) + 0) * _nb_locations + l;
143         _edge_lengths[e] = 0.0;
144         e++;
145       }
146       if(_exits[l]) {
147         node_from[e] =   1 + (2 * (t + 0) + 1) * _nb_locations + l;
148         node_to[e] = sink;
149         _edge_lengths[e] = 0.0;
150         e++;
151       }
152     }
153   }
154
155   _graph = new MTPGraph(nb_vertices, nb_edges,
156                         node_from, node_to,
157                         source, sink);
158
159   delete[] node_from;
160   delete[] node_to;
161 }
162
163 void Tracker::print_dot_graph(ostream *os) {
164   _graph->print_dot(os);
165 }
166
167 void Tracker::track() {
168   int e = 0;
169   for(int t = 0; t < _nb_time_steps; t++) {
170     for(int l = 0; l < _nb_locations; l++) {
171       _edge_lengths[e++] = - _detection_score[t][l];
172     }
173   }
174
175   _graph->find_best_paths(_edge_lengths);
176   _graph->retrieve_disjoint_paths();
177
178 #ifdef VERBOSE
179   for(int p = 0; p < _graph->nb_paths; p++) {
180     Path *path = _graph->paths[p];
181     cout << "PATH " << p << " [length " << path->length << "] " << path->nodes[0];
182     for(int n = 1; n < path->length; n++) {
183       cout << " -> " << path->nodes[n];
184     }
185     cout << endl;
186   }
187 #endif
188 }
189
190 int Tracker::nb_trajectories() {
191   return _graph->nb_paths;
192 }
193
194 int Tracker::trajectory_entrance_time(int k) {
195   return (_graph->paths[k]->nodes[1] - 1) / (2 * _nb_locations);
196 }
197
198 int Tracker::trajectory_duration(int k) {
199   return (_graph->paths[k]->length - 2) / 2;
200 }
201
202 int Tracker::trajectory_location(int k, int time) {
203   return (_graph->paths[k]->nodes[2 * time + 1] - 1) % _nb_locations;
204 }