00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <algorithm>
00015 #include "base/hash.h"
00016 #include <utility>
00017 #include <vector>
00018
00019 #include "base/callback.h"
00020 #include "base/scoped_ptr.h"
00021 #include "base/hash.h"
00022
00023 namespace operations_research {
00024
00025 namespace {
00026
00027 void Search(ResultCallback2<bool, int, int>* const graph,
00028 ResultCallback1<bool, const std::vector<int>&>* const callback,
00029 int* input_candidates,
00030 int input_size,
00031 int input_candidate_size,
00032 std::vector<int>* actual,
00033 bool* stop) {
00034 std::vector<int> actual_candidates(input_candidate_size);
00035 int pre_increment = 0;
00036 int pivot = 0;
00037 int actual_candidate_size;
00038 int actual_size;
00039 int start = 0;
00040 int index = input_candidate_size;
00041
00042
00043 for (int i = 0; i < input_candidate_size && index != 0; ++i) {
00044 int p = input_candidates[i];
00045 int count = 0;
00046 int position = 0;
00047
00048
00049 for (int j = input_size; j < input_candidate_size && count < index; ++j) {
00050 if (!graph->Run(p, input_candidates[j])) {
00051 count++;
00052
00053 position = j;
00054 }
00055 }
00056
00057
00058 if (count < index) {
00059 pivot = p;
00060 index = count;
00061
00062 if (i < input_size) {
00063 start = position;
00064 } else {
00065 start = i;
00066
00067 pre_increment = 1;
00068 }
00069 }
00070 }
00071
00072
00073
00074
00075 for (int nod = index + pre_increment; nod >= 1; nod--) {
00076
00077 int selected = input_candidates[start];
00078 input_candidates[start] = input_candidates[input_size];
00079 input_candidates[input_size] = selected;
00080
00081
00082 actual_candidate_size = 0;
00083
00084 for (int i = 0; i < input_size; ++i) {
00085 if (graph->Run(selected, input_candidates[i])) {
00086 actual_candidates[actual_candidate_size++] = input_candidates[i];
00087 }
00088 }
00089
00090
00091 actual_size = actual_candidate_size;
00092
00093 for (int i = input_size + 1; i < input_candidate_size; ++i) {
00094 if (graph->Run(selected, input_candidates[i])) {
00095 actual_candidates[actual_size++] = input_candidates[i];
00096 }
00097 }
00098
00099
00100 actual->push_back(selected);
00101
00102
00103 if (actual_size == 0) {
00104 *stop = callback->Run(*actual);
00105 } else {
00106 if (actual_candidate_size < actual_size) {
00107 Search(graph, callback, actual_candidates.data(),
00108 actual_candidate_size, actual_size, actual, stop);
00109 if (*stop) {
00110 return;
00111 }
00112 }
00113 }
00114
00115
00116
00117 actual->pop_back();
00118
00119
00120 input_size++;
00121
00122 if (nod > 1) {
00123
00124 start = input_size;
00125 while (graph->Run(pivot, input_candidates[start])) {
00126 start++;
00127 }
00128 }
00129
00130 }
00131 }
00132
00133 class FindAndEliminate {
00134 public:
00135 FindAndEliminate(ResultCallback2<bool, int, int>* const graph,
00136 int node_count,
00137 ResultCallback1<bool, const std::vector<int>&>* const callback)
00138 : graph_(graph), node_count_(node_count), callback_(callback) {}
00139
00140 bool GraphCallback(int node1, int node2) {
00141 if (visited_.find(
00142 std::make_pair(std::min(node1, node2),
00143 std::max(node1, node2))) != visited_.end()) {
00144 return false;
00145 }
00146 return graph_->Run(node1, node2);
00147 }
00148
00149 bool SolutionCallback(const std::vector<int>& solution) {
00150 const int size = solution.size();
00151 if (size > 1) {
00152 for (int i = 0; i < size - 1; ++i) {
00153 for (int j = i + 1; j < size; ++j) {
00154 visited_.insert(std::make_pair(std::min(solution[i], solution[j]),
00155 std::max(solution[i], solution[j])));
00156 }
00157 }
00158 callback_->Run(solution);
00159 }
00160 return false;
00161 }
00162
00163 private:
00164 ResultCallback2<bool, int, int>* const graph_;
00165 int node_count_;
00166 ResultCallback1<bool, const std::vector<int>&>* const callback_;
00167 #if defined(_MSC_VER)
00168 hash_set<std::pair<int, int>, PairIntHasher> visited_;
00169 #else
00170 hash_set<std::pair<int, int> > visited_;
00171 #endif
00172 };
00173 }
00174
00175
00176
00177 void FindCliques(ResultCallback2<bool, int, int>* const graph,
00178 int node_count,
00179 ResultCallback1<bool, const std::vector<int>&>* const callback) {
00180 graph->CheckIsRepeatable();
00181 callback->CheckIsRepeatable();
00182 scoped_array<int> initial_candidates(new int[node_count]);
00183 std::vector<int> actual;
00184
00185 scoped_ptr<ResultCallback2<bool, int, int> > graph_deleter(graph);
00186 scoped_ptr<ResultCallback1<bool, const std::vector<int>&> > callback_deleter(
00187 callback);
00188
00189 for (int c = 0; c < node_count; ++c) {
00190 initial_candidates[c] = c;
00191 }
00192
00193 bool stop = false;
00194 Search(graph, callback, initial_candidates.get(), 0, node_count, &actual,
00195 &stop);
00196 }
00197
00198
00199 void CoverArcsByCliques(
00200 ResultCallback2<bool, int, int>* const graph,
00201 int node_count,
00202 ResultCallback1<bool, const std::vector<int>&>* const callback) {
00203 graph->CheckIsRepeatable();
00204 callback->CheckIsRepeatable();
00205
00206 scoped_ptr<ResultCallback2<bool, int, int> > graph_deleter(graph);
00207 scoped_ptr<ResultCallback1<bool, const std::vector<int>&> > callback_deleter(
00208 callback);
00209
00210 FindAndEliminate cache(graph, node_count, callback);
00211 scoped_array<int> initial_candidates(new int[node_count]);
00212 std::vector<int> actual;
00213
00214 scoped_ptr<ResultCallback2<bool, int, int> > cached_graph(
00215 NewPermanentCallback(&cache, &FindAndEliminate::GraphCallback));
00216 scoped_ptr<ResultCallback1<bool, const std::vector<int>&> >cached_callback(
00217 NewPermanentCallback(&cache, &FindAndEliminate::SolutionCallback));
00218
00219 for (int c = 0; c < node_count; ++c) {
00220 initial_candidates[c] = c;
00221 }
00222
00223 bool stop = false;
00224 Search(cached_graph.get(), cached_callback.get(),
00225 initial_candidates.get(), 0,
00226 node_count, &actual, &stop);
00227 }
00228
00229
00230 }