-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathSparseDP_Forward.h
491 lines (404 loc) · 19 KB
/
SparseDP_Forward.h
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
// This program is implemented Sparse Dynamic Programming algorithm described in David Eppstein paper
// Author: Jingwen Ren
#ifndef SPARSE_DP_FORWARD_
#define SPARSE_DP_FORWARD_
#include <iostream>
#include <string>
#include <utility>
#include <algorithm> // std::lower_bound
#include <numeric> //std::floor
#include <cmath>
#include <set>
#include <iterator>
#include <assert.h>
#include <chrono> // generate random number
#include <random> // generate random number
#include <type_traits>
#include "SubProblem.h"
#include "Sorting.h"
#include "SubRountine.h"
#include "Fragment_Info.h"
#include "Info.h"
// #include "overload.h"
#include "DivideSubByRow1.h"
#include "DivideSubByCol1.h"
#include "DivideSubByRow2.h"
#include "DivideSubByCol2.h"
#include "Point.h"
#include "TupleOps.h"
#include "Options.h"
#include "Clustering.h"
using std::cerr;
using std::cout;
using std::endl;
using std::iota;
// Note: Each fragment has the same length
void
ProcessPoint_ForwardOnly (const std::vector<Point> & H1, const vector<int> &MatchLengths, std::vector<info> & V, StackOfSubProblems & SubR1, StackOfSubProblems & SubC1,
std::vector<Fragment_Info> & Value, const Options & opts, const std::vector<float> & LookUpTable, int rate) {
//ProcessPoint (const std::vector<Point> & H1, const std::vector<unsigned int> & H3, std::vector<info> & V, StackOfSubProblems & SubR, StackOfSubProblems & SubC,
// std::vector<Fragment_Info> & Value, const Options & opts, const std::vector<float> & LookUpTable, int rate) {
bool step_sdp = 1;
for (unsigned int i = 0; i < H1.size(); ++i) { // process points by row
long int ForwardDiag = static_cast<long int>(H1[i].se.second) - static_cast<long int>(H1[i].se.first);
//cerr << "\n\n\n\nprocessing point " << H1[H3[i]] << endl;
//cerr << "the Value[" << H1[H3[i]].frag_num << "] of this point: " << Value[H1[H3[i]].frag_num] << "\n";
unsigned int ii = H1[i].frag_num;
if (H1[i].ind == 1 and H1[i].inv == 1) { // H1[i] is a start point s1
//cerr << "----------------------------------------this is a start point (s1) ------------------------------------" << endl;
//cerr << "dealing with the subproblem B first. Solve Value[" << H1[i].frag_num << "].SS_B_R1 and SS_B_C1" << endl;
//cerr <<"----------------Solve SS_B_R1 -------------------" << endl;
//
// For each subproblem B_R1 that point H1[i] is in, get Ev[ForwardDiag] and update Value[H1[i]].frag_num].val
//
for (unsigned int k = 0; k < Value[ii].SS_B_R1.size(); ++k) {
unsigned int j = Value[ii].SS_B_R1[Value[ii].SS_B_R1.size() - 1 - k];
//cerr << "Solving SubR1[" << j << "]: " << SubR1[j]<< "\n";
// If subproblem SubR1[j] is a leaf case, then
if (SubR1[j].Di.empty()) {
//cerr << "SubR1[" << j << "] is a leaf case or non-leaf case but Di is empty" << "\n";
--Value[ii].counter_B_R1;
continue;
}
else {
// Then subproblem SubR1[j] is non-leaf case. find the index of the point in E array
std::vector<unsigned int>::iterator t = Lower_Bound<std::vector<unsigned int>::iterator,long int>(SubR1[j].E.begin(), SubR1[j].E.end(), ForwardDiag, SubR1[j].Ei);
//cerr << "SubR1[" << j << "] is a non-leaf case! Find the index of the point in E array" << "/n";
//cerr << "SubR1[" << j << "].Ei: " << SubR1[j].Ei << "/n";
//cerr << "The index of this point in E array: " << *t << "\n";
if (SubR1[j].Eb[*t] == -1) {
//cerr << "SubR1[" << j << "] is a non-leaf case but there is no forward diag smaller than the current in D array" << endl;
--Value[ii].counter_B_R1;
continue;
}
else {
//assert(SubR1[j].counter_D[SubR1[j].Eb[*t]] == 0);
//cerr << "SubR1[" << j << "] is a non-leaf case and The part of D array where forward diags are smaller than current is filled out already." << endl;
//cerr << "Start to compute the maximization structure.\n";
SubR1[j].now = SubR1[j].Eb[*t];
Maximization (SubR1[j].now, SubR1[j].last, SubR1[j].Di, SubR1[j].Ei, SubR1[j].Dv, SubR1[j].Db, SubR1[j].Block, SubR1[j].S_1, LookUpTable, opts, step_sdp); // TODO(Jingwen) anything change for SubC????
SubR1[j].last = SubR1[j].Eb[*t];
//cerr << "retrieve the value from the maximization structure\n";
unsigned int i1 = *t; // i1 stores the index in Ei that ForwardDiag is in
unsigned int i2; // i2 stores the index in Di which is the best candidate for ForwardDiag
FindValueInBlock(ForwardDiag, SubR1[j].S_1, SubR1[j].Ei, SubR1[j].Block, i1, i2);
//cerr << "the index in Ei that ForwardDiag is in----i1: " << i1 << "\n";
//cerr << "the index in Di which is the best candidate for ForwardDiag ---- i2: " << i2 << "\n";
SubR1[j].Ev[i1] = SubR1[j].Dv[i2] + w(SubR1[j].Di[i2], SubR1[j].Ei[i1], LookUpTable, opts, step_sdp) + MatchLengths[ii] * rate; //opts.globalK * rate;
SubR1[j].Ep[i1] = i2;
//cerr << "SubR1[" << j << "].Ev[" << i1 << "]: " << SubR1[j].Ev[i1] << ", SubR1[" << j << "].Ep[" << i1 << "]: " << SubR1[j].Ep[i1] << "\n";
// Update the value of this point
//TODO(Jingwen): if this point is a s1 of a reverse orientated anchor, only update the value when SubR1[j].Dp[Ep[i1]] points to a forward orientated anchor
//TODO(Jingwen): only for debug
assert(Value[ii].orient == H1[i].orient);
int p = SubR1[j].Dp[SubR1[j].Ep[i1]];
// if the current anchor is reverse oriented and the previous anchor is also reverse oriented, then do not update Value[ii]
// Otherwise update Value[ii]
if (! (Value[ii].orient == 0 and Value[p].orient == 0)) {
if (Value[ii].val < SubR1[j].Ev[i1]) {
Value[ii].val = SubR1[j].Ev[i1];
Value[ii].prev_sub = SubR1[j].num;
Value[ii].prev_ind = i1;
Value[ii].prev = 1; // the best value comes from row subproblem
Value[ii].inv = 1; // the best value comes from SubR1
//cerr << "update the value of this point\n";
//cerr << "Value[ii].val: " << Value[ii].val << ", Value[ii].prev_sub: " << Value[ii].prev_sub << ", Value[ii].prev_ind: " << Value[ii].prev_ind <<
//", Value[ii].prev: " << Value[ii].prev << endl;
}
}
--Value[ii].counter_B_R1;
//cerr << "Do not update the value of this point\n";
}
}
}
//cerr << endl << endl;
//cerr << "--------------Solve SS_B_C1 ----------------" << endl;
// For each subproblem B_C1 that point H1[i] is in, get Ev[H1[i].first - H1[i].second] and update Value[H1[i]].val
for (unsigned int k = 0; k < Value[ii].SS_B_C1.size(); ++k) {
unsigned int j = Value[ii].SS_B_C1[Value[ii].SS_B_C1.size() - 1 - k];
//cerr << "SubC1[" << j << "]: " << SubC1[j]<< "\n";
// If subproblem SubC1[j] is a leaf case, then
if (SubC1[j].Di.empty()) {
//cerr << "SubC1[" << j << "] is a leaf case or it's a non-leaf case with an empty Di" << "\n";
--Value[ii].counter_B_C1;
continue;
}
else {
// find the index of this point in E array
std::vector<unsigned int>::reverse_iterator t = Lower_Bound<std::vector<unsigned int>::reverse_iterator,long int>(SubC1[j].E.rbegin(), SubC1[j].E.rend(), ForwardDiag, SubC1[j].Ei);
//cerr << "SubC1[" << j << "] is a non-leaf case! Find the index of the point in E array" << "/n";
//cerr << "SubC1[" << j << "].Ei: " << SubC1[j].Ei << "/n";
//cerr << "The index of this point in E array: " << *t << "\n";
if (SubC1[j].Eb[*t] == -1) {
//cerr << "SubC1[" << j << "] is a non-leaf case but there is no forward diag larger than the current\n ";
--Value[ii].counter_B_C1;
continue;
}
else {
//assert(SubC1[j].counter_D[SubC1[j].Eb[*t]] == 0);
//cerr << "SubC1[" << j << "] is a non-leaf case and The part of D array where forward diags are smaller than current is filled out already.\n";
//cerr << "Start to compute the maximization structure.\n";
SubC1[j].now = SubC1[j].Eb[*t];
Maximization (SubC1[j].now, SubC1[j].last, SubC1[j].Di, SubC1[j].Ei, SubC1[j].Dv, SubC1[j].Db, SubC1[j].Block, SubC1[j].S_1, LookUpTable, opts, step_sdp);
SubC1[j].last = SubC1[j].Eb[*t];
//cerr << "retrieve the value from the maximization structure\n";
unsigned int i1 = *t; // i1 stores the index in Ei that ForwardDiag is in
unsigned int i2; // i2 stores the index in Di which is the best candidate for ForwardDiag
FindValueInBlock(ForwardDiag, SubC1[j].S_1, SubC1[j].Ei, SubC1[j].Block, i1, i2);
//cerr << "the index in Ei that ForwardDiag is in----i1: " << i1 << "\n";
//cerr << "the index in Di which is the best candidate for ForwardDiag ---- i2: " << i2 << "\n";
// SubC1[j].Ev[i1] = SubC1[j].Dv[i2] + w(SubC1[j].Di[i2], SubC1[j].Ei[i1], LookUpTable, opts) + opts.globalK;
// SubC1[j].Ep[i1] = i2;
SubC1[j].Ev[i1] = SubC1[j].Dv[i2] + w(SubC1[j].Di[i2], SubC1[j].Ei[i1], LookUpTable, opts, step_sdp) + MatchLengths[ii] * rate; //opts.globalK * rate;
SubC1[j].Ep[i1] = i2;
//cerr << "SubC1[" << j << "].Ev[" << i1 << "]: " << SubC1[j].Ev[i1] << ", SubC1[" << j << "].Ep[" << i1 << "]: " << SubC1[j].Ep[i1] << "\n";
// Update the value of this point
//TODO(Jingwen): if this point is a s1 of a reverse orientated anchor, only update the value when SubR1[j].Dp[Ep[i1]] points to a forward orientated anchor
//TODO(Jingwen): Only for debug
assert(Value[ii].orient == H1[i].orient);
int p = SubC1[j].Dp[SubC1[j].Ep[i1]];
//
// If the current anchor is reverse oriented and the previous anchor is also reverse oriented, then do not update Value[ii]
// Otherwise update Value[ii]
if (! (Value[ii].orient == 0 and Value[p].orient == 0)) {
if (Value[ii].val < SubC1[j].Ev[i1]) {
Value[ii].val = SubC1[j].Ev[i1];
Value[ii].prev_sub = SubC1[j].num;
Value[ii].prev_ind = i1;
Value[ii].prev = 0; // the best value comes from col subproblem
Value[ii].inv = 1; // the best value comes from SubC1
//cerr << "update the value of this point\n";
//cerr << "Value[ii].val: " << Value[ii].val << ", Value[ii].prev_sub: " << Value[ii].prev_sub << ", Value[ii].prev_ind: " << Value[ii].prev_ind <<
//", Value[ii].prev: " << Value[ii].prev << endl;
}
}
--Value[ii].counter_B_C1;
//cerr << "Do not update the value of this point\n";
}
}
}
}
else if (H1[i].ind == 0 and H1[i].inv == 1) { // H1[i] is an end point (e1)
//cerr << "---------------------------------This is an end point (e1) --------------------------------"<< endl;
//cerr << "Pass the value Value[ii].val to SS_A_R1 and SS_A_C1" << endl;
// If all the subproblems B that the point H1[i] is in are already processed, then Value[H1[i]].val is ready
// For each subproblem A that the point H1[i] is in, Pass the Value[H1[i]].val to the D array
PassValueToD1(ii, Value, H1, SubR1, SubC1, ForwardDiag);
}
}
}
// void
// TraceBack_ForwardOnly (StackOfSubProblems & SubR1, StackOfSubProblems & SubC1, const vector<Fragment_Info> & Value,
// unsigned int i, vector<unsigned int> & Chain) {
// long int prev_sub = Value[i].prev_sub;
// long int prev_ind = Value[i].prev_ind;
// Chain.push_back(i);
// if (prev_sub != -1 and prev_ind != -1) {
// // if (Value[i].prev == 1 and Value[i].inv == 1) { // The previous subproblem is SubR1
// // unsigned int ind = SubR1[prev_sub].Ep[prev_ind];
// // TraceBack_ForwardOnly(SubR1, SubC1, Value, SubR1[prev_sub].Dp[ind], FinalChain);
// // }
// if (Value[i].prev == 1 and Value[i].inv == 1) { // The previous subproblem is SubR1
// assert(prev_sub < SubR1.StackSub.size());
// assert(prev_ind < SubR1[prev_sub].Ep.size());
// unsigned int ind = SubR1[prev_sub].Ep[prev_ind];
// assert(ind < SubR1[prev_sub].Dp.size());
// i = SubR1[prev_sub].Dp[ind];
// //TraceBack(SubR1, SubC1, SubR2, SubC2, Value, SubR1[prev_sub].Dp[ind], Chain);
// }
// else if (Value[i].prev == 0 and Value[i].inv == 1) { // The previous subproblem is SubC1
// assert(prev_sub < SubC1.StackSub.size());
// assert(prev_ind < SubC1[prev_sub].Ep.size());
// unsigned int ind = SubC1[prev_sub].Ep[prev_ind];
// assert(ind < SubC1[prev_sub].Dp.size());
// i = SubC1[prev_sub].Dp[ind];
// //TraceBack(SubR1, SubC1, SubR2, SubC2, Value, SubC1[prev_sub].Dp[ind], Chain);
// }
// // else if (Value[i].prev == 0 and Value[i].inv == 1) { // The previous subproblem is SubC1
// // unsigned int ind = SubC1[prev_sub].Ep[prev_ind];
// // TraceBack_ForwardOnly(SubR1, SubC1, Value, SubC1[prev_sub].Dp[ind], FinalChain);
// // }
// prev_sub = Value[i].prev_sub;
// prev_ind = Value[i].prev_ind;
// Chain.push_back(i);
// }
// }
//
// This function is for tracing back a chain;
//
void
TraceBack_ForwardOnly (StackOfSubProblems & SubR1, StackOfSubProblems & SubC1, const vector<Fragment_Info> & Value,
unsigned int i, vector<unsigned int> & Chain) {
long int prev_sub = Value[i].prev_sub;
long int prev_ind = Value[i].prev_ind;
Chain.push_back(i);
//cerr << "i: " << i << endl;
while (prev_sub != -1 and prev_ind != -1) {
if (Value[i].prev == 1 and Value[i].inv == 1) { // The previous subproblem is SubR1
assert(prev_sub < SubR1.StackSub.size());
assert(prev_ind < SubR1[prev_sub].Ep.size());
unsigned int ind = SubR1[prev_sub].Ep[prev_ind];
assert(ind < SubR1[prev_sub].Dp.size());
i = SubR1[prev_sub].Dp[ind];
//TraceBack(SubR1, SubC1, SubR2, SubC2, Value, SubR1[prev_sub].Dp[ind], Chain);
}
else if (Value[i].prev == 0 and Value[i].inv == 1) { // The previous subproblem is SubC1
assert(prev_sub < SubC1.StackSub.size());
assert(prev_ind < SubC1[prev_sub].Ep.size());
unsigned int ind = SubC1[prev_sub].Ep[prev_ind];
assert(ind < SubC1[prev_sub].Dp.size());
i = SubC1[prev_sub].Dp[ind];
//TraceBack(SubR1, SubC1, SubR2, SubC2, Value, SubC1[prev_sub].Dp[ind], Chain);
}
prev_sub = Value[i].prev_sub;
prev_ind = Value[i].prev_ind;
Chain.push_back(i);
}
}
// The input for this function is GenomePairs which is from gapPairs (from snd SDP)
// Each fragment has the same length
//
int SparseDP_ForwardOnly (const GenomePairs &FragInput, const vector<int> &MatchLengths, std::vector<unsigned int> &chain, const Options &opts,
const std::vector<float> &LookUpTable, float &inv_value, int &inv_NumOfAnchors, int rate = 5) {
if (FragInput.size() == 0) return 0;
std::vector<Point> H1;
// FragInput is vector<GenomePair>
// get points from FragInput and store them in H1
for (unsigned int i = 0; i < FragInput.size(); i++) {
// insert start point s1 into H1
Point s1;
H1.push_back(s1);
H1.back().ind = 1; // start
H1.back().inv = 1; // forward direction
H1.back().frag_num = i;
H1.back().se.first = FragInput[i].first.pos;
H1.back().se.second = FragInput[i].second.pos;
H1.back().orient = 1; // the point comes from a forward oriented anchor
// insert end point e1 into H1
Point e1;
H1.push_back(e1);
H1.back().ind = 0; // end
H1.back().inv = 1; // forward direction
H1.back().frag_num = i;
H1.back().se.first = FragInput[i].first.pos + MatchLengths[i];
H1.back().se.second = FragInput[i].second.pos + MatchLengths[i];
}
//Sort the point by row
sort(H1.begin(), H1.end(), SortByRowOp<Point>()); // with same q and t coordinates, end point < start point
//cerr << "H1: " << H1 << endl;
std::vector<unsigned int> H2(H1.size());
//std::vector<unsigned int> H3(H1.size()); // TODO(Jingwen): Probably don't need this
iota(H2.begin(), H2.end(), 0);
//iota(H3.begin(), H3.end(), 0);
//Sort the point by column and by back diagonal
sort(H2.begin(), H2.end(), SortByColOp<Point, unsigned int>(H1));
//sort(H3.begin(), H3.end(), SortByBackDiagOp<Point, unsigned int>(H1));
// print out H2, and H3
/*
cerr << "H2: [";
for (unsigned int t = 0; t < H2.size(); ++t) {
cerr << H1[H2[t]] << endl;
}
cerr << "]\n";
cerr << "H3: [";
for (unsigned int t = 0; t < H2.size(); ++t) {
cerr << H1[H3[t]] << endl;
}
cerr << "]\n";
*/
std::vector<info> Row;
std::vector<info> Col;
GetRowInfo(H1, Row);
GetColInfo(H1, H2, Col);
//cerr << "Row: " << Row << "\n";
//cerr << "Col: " << Col << "\n";
unsigned int n1 = 0;
unsigned int m1 = 0;
//std::vector<Subproblem> SubR;
//std::vector<Subproblem> SubC;
StackOfSubProblems SubR1;
StackOfSubProblems SubC1;
int eeR1 = 0, eeC1 = 0;
//cerr << "DivideSubByRow\n";
DivideSubProbByRow1(H1, Row, 0, Row.size(), n1, SubR1, eeR1);
//cerr << "SubR: " << SubR << endl;
//cerr << "DivideSubByCol\n";
DivideSubProbByCol1(H1, H2, Col, 0, Col.size(), m1, SubC1, eeC1);
//cerr << "SubC: " << SubC << endl;
// Get SS_A_R1, SS_B_R1 for each fragment
std::vector<Fragment_Info> Value(FragInput.size());
for (unsigned int t = 0; t < Row.size(); ++t) {
for (unsigned int tt = Row[t].pstart; tt < Row[t].pend; ++tt) {
unsigned int ii = H1[tt].frag_num;
if (H1[tt].ind == 1 and H1[tt].inv == 1) { //H1[tt] is a start point (s1)
Value[ii].SS_B_R1 = Row[t].SS_B1;
Value[ii].counter_B_R1 = Row[t].SS_B1.size();
Value[ii].val = MatchLengths[ii]*rate; //opts.globalK * rate;
Value[ii].orient = H1[tt].orient;
}
else if (H1[tt].ind == 0 and H1[tt].inv == 1) { // H1[tt] is an end point (e1)
Value[ii].SS_A_R1 = Row[t].SS_A1;
Value[ii].counter_A_R1 = Row[t].SS_A1.size();
//Value[ii].val = (opts.globalK); // TODO(Jingwen): make sure that this is redundant
}
}
}
// Get SS_A_C2 and SS_B_C2 for each fragment
for (unsigned int t = 0; t < Col.size(); ++t) {
for (unsigned int tt = Col[t].pstart; tt < Col[t].pend; ++tt) {
unsigned int ii = H1[H2[tt]].frag_num;
if (H1[H2[tt]].ind == 1 and H1[H2[tt]].inv == 1) { //H1[H2[tt]] a start point (s1)
Value[ii].SS_B_C1 = Col[t].SS_B1;
Value[ii].counter_B_C1 = Col[t].SS_B1.size();
Value[ii].val = MatchLengths[ii]*rate; // opts.globalK * rate;
}
else if (H1[H2[tt]].ind == 0 and H1[H2[tt]].inv == 1) { // H1[H2[tt]] is an end point (e1)
Value[ii].SS_A_C1 = Col[t].SS_A1;
Value[ii].counter_A_C1 = Col[t].SS_A1.size();
//Value[ii].val = (opts.globalK);
}
}
}
//cerr << "Value: " << Value << endl;
//cerr << "ProcessPoint\n";
ProcessPoint_ForwardOnly(H1, MatchLengths, Row, SubR1, SubC1, Value, opts, LookUpTable, rate);
//cerr << "end\n";
// find the max_value for the FinalChain
unsigned int l = 0;
float max_value = 0;
unsigned int max_pos = 0;
while (l < Value.size()) {
if (Value[l].val > max_value) {
max_value = Value[l].val;
max_pos = l;
}
++l;
}
inv_value = max_value;
inv_NumOfAnchors = chain.size();
//cerr << "TraceBack\n";
// Trace back to get the FinalChain
// store the index of points
chain.clear();
TraceBack_ForwardOnly(SubR1, SubC1, Value, max_pos, chain);
//std::reverse(chain.begin(), chain.end());
// Clear SubR and SubC
// SubR1.Clear(eeR1);
// SubC1.Clear(eeC1);
SubR1.clear();
SubC1.clear();
Value.clear();
Row.clear();
Col.clear();
H1.clear();
H2.clear();
/* // print out the final chain
cerr << "FinalChain: (";
for (unsigned int i = 0; i < FinalChain.size(); ++i) {
cerr << A[FinalChain[i]] << ", ";
}
cerr << ")" << endl;
*/
return 0;
}
#endif