-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathfinder.cpp
More file actions
142 lines (130 loc) · 4.26 KB
/
finder.cpp
File metadata and controls
142 lines (130 loc) · 4.26 KB
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
#include "mine/finder.hpp"
#include <fstream>
#include <iomanip>
#include <set>
#include <sstream>
#include "lang/analyzer.hpp"
#include "lang/constants.hpp"
#include "lang/program_util.hpp"
#include "lang/subprogram.hpp"
#include "mine/config.hpp"
#include "mine/invalid_matches.hpp"
#include "seq/seq_list.hpp"
#include "seq/seq_program.hpp"
#include "sys/file.hpp"
#include "sys/log.hpp"
#include "sys/setup.hpp"
#include "sys/util.hpp"
Finder::Finder(const Settings &settings, Evaluator &evaluator)
: settings(settings),
evaluator(evaluator),
optimizer(settings),
minimizer(settings),
num_find_attempts(0),
invalid_matches(),
checker(settings, evaluator, minimizer, invalid_matches) {
auto config = ConfigLoader::load(settings);
if (config.matchers.empty()) {
Log::get().error("No matchers defined", true);
}
// create matchers
matchers.clear();
for (auto m : config.matchers) {
try {
auto matcher = Matcher::Factory::create(m);
matchers.emplace_back(std::move(matcher));
} catch (const std::exception &) {
Log::get().warn("Ignoring error while loading " + m.type + " matcher");
}
}
}
void Finder::insert(const Sequence &norm_seq, UID id) {
for (auto &matcher : matchers) {
matcher->insert(norm_seq, id);
}
}
void Finder::remove(const Sequence &norm_seq, UID id) {
for (auto &matcher : matchers) {
matcher->remove(norm_seq, id);
}
}
Matcher::seq_programs_t Finder::findSequence(const Program &p,
Sequence &norm_seq,
const SequenceIndex &sequences) {
// update memory usage info
if (num_find_attempts++ % 1000 == 0) {
bool has_memory = Setup::hasMemory();
for (const auto &matcher : matchers) {
matcher->has_memory = has_memory;
}
}
// determine largest memory cell to check
int64_t max_index = 20; // magic number
int64_t largest_used_cell;
if (ProgramUtil::getUsedMemoryCells(p, nullptr, nullptr, largest_used_cell,
settings.max_memory) &&
largest_used_cell <= 100) { // magic number
max_index = largest_used_cell;
}
// interpret program
tmp_seqs.resize(std::max<size_t>(2, max_index + 1));
Matcher::seq_programs_t result;
try {
evaluator.eval(p, tmp_seqs);
norm_seq = tmp_seqs[1];
} catch (const std::exception &) {
// evaluation error
return result;
}
Program p2 = p;
p2.push_back(Operation::Type::MOV, Operand::Type::DIRECT,
Program::OUTPUT_CELL, Operand::Type::DIRECT, 0);
for (size_t i = 0; i < tmp_seqs.size(); i++) {
if (i == Program::OUTPUT_CELL) {
findAll(p, tmp_seqs[i], sequences, result);
} else {
p2.ops.back().source.value = i;
findAll(p2, tmp_seqs[i], sequences, result);
}
}
return result;
}
void Finder::findAll(const Program &p, const Sequence &norm_seq,
const SequenceIndex &sequences,
Matcher::seq_programs_t &result) {
// collect possible matches
std::pair<UID, Program> last(UID('A', 0), Program());
for (size_t i = 0; i < matchers.size(); i++) {
tmp_result.clear();
matchers[i]->match(p, norm_seq, tmp_result);
// validate the found matches
for (auto t : tmp_result) {
auto &s = sequences.get(t.first);
if (t == last) {
// Log::get().warn("Ignoring duplicate match for " + s.id_str());
continue;
}
last = t;
auto expected_seq = s.getTerms(s.numExistingTerms());
auto num_required = SequenceProgram::getNumRequiredTerms(t.second);
auto res = evaluator.check(t.second, expected_seq, num_required, t.first);
if (res.first == status_t::ERROR) {
invalid_matches.insert(t.first);
// Log::get().warn( "Ignoring invalid match for " + s.id_str() );
} else {
result.push_back(t);
// Log::get().info( "Found potential match for " + s.id_str() );
}
}
}
}
void Finder::logSummary(size_t loaded_count) {
std::stringstream buf;
buf << "Matcher compaction ratios: ";
for (size_t i = 0; i < matchers.size(); i++) {
if (i > 0) buf << ", ";
buf << matchers[i]->getName() << ": " << std::setprecision(3)
<< matchers[i]->getCompationRatio() << "%";
}
Log::get().debug(buf.str());
}