From 2412c08dcd6cb50e56355a2997e9f21d70da97b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Fri, 25 Mar 2022 17:14:18 +0100 Subject: Algorithms : complete 05-advanced_algorithms_and_complexity 03-np-completness --- .../01-gsm_network/gsm_network.cpp | 39 ++++++++++--- .../02-cleaning_apartment/cleaning_apartment.cpp | 66 +++++++++++++++++++--- .../03-budget_allocation/budget_allocation.cpp | 59 ++++++++++++++++--- 3 files changed, 143 insertions(+), 21 deletions(-) diff --git a/05-advanced_algorithms_and_complexity/03-np-completness/01-gsm_network/gsm_network.cpp b/05-advanced_algorithms_and_complexity/03-np-completness/01-gsm_network/gsm_network.cpp index 5eafa18..ff53c87 100644 --- a/05-advanced_algorithms_and_complexity/03-np-completness/01-gsm_network/gsm_network.cpp +++ b/05-advanced_algorithms_and_complexity/03-np-completness/01-gsm_network/gsm_network.cpp @@ -18,14 +18,39 @@ struct ConvertGSMNetworkProblemToSat { edges(m) { } + static inline int var(int vertex, int color) { return vertex * 3 + color; } + void printEquisatisfiableSatFormula() { - // This solution prints a simple satisfiable formula - // and passes about half of the tests. - // Change this function to solve the problem. - cout << "3 2" << endl; - cout << "1 2 0" << endl; - cout << "-1 -2 0" << endl; - cout << "1 -2 0" << endl; + vector> clauses; + + // 1 color per vertex + for (int i = 0; i < numVertices; i++) { + // at least one var must be true + clauses.push_back({var(i, 1), var(i, 2), var(i, 3)}); // R || G || B + // both can't be true + clauses.push_back({-var(i, 1), -var(i, 2)}); // !R || !G + clauses.push_back({-var(i, 1), -var(i, 3)}); // !R || !B + clauses.push_back({-var(i, 2), -var(i, 3)}); // !B || !G + } + + // 2 colors per edge + for (Edge e : edges) { + int from = e.from - 1; + int to = e.to - 1; + // both can't be true + clauses.push_back({-var(from, 1), -var(to, 1)}); // !R || !R + clauses.push_back({-var(from, 2), -var(to, 2)}); // !G || !G + clauses.push_back({-var(from, 3), -var(to, 3)}); // !B || !B + } + + cout << clauses.size() << " " << numVertices * 3 << endl; + for (vector& c : clauses) { + for (int v : c) { + cout << v << " "; + } + cout << "0" << endl; + } + cout << endl; } }; diff --git a/05-advanced_algorithms_and_complexity/03-np-completness/02-cleaning_apartment/cleaning_apartment.cpp b/05-advanced_algorithms_and_complexity/03-np-completness/02-cleaning_apartment/cleaning_apartment.cpp index 5690be7..a205158 100644 --- a/05-advanced_algorithms_and_complexity/03-np-completness/02-cleaning_apartment/cleaning_apartment.cpp +++ b/05-advanced_algorithms_and_complexity/03-np-completness/02-cleaning_apartment/cleaning_apartment.cpp @@ -15,14 +15,66 @@ struct ConvertHampathToSat { edges(m) { } + // matrix of vertices * vertices (+1 because 0 is reserved) + static inline int var(int v1, int v2, int n) { return 1 + v1 * n + v2; } + void printEquisatisfiableSatFormula() { - // This solution prints a simple satisfiable formula - // and passes about half of the tests. - // Change this function to solve the problem. - cout << "3 2" << endl; - cout << "1 2 0" << endl; - cout << "-1 -2 0" << endl; - cout << "1 -2 0" << endl; + vector> clauses; + vector cstrs; + + for (int i = 0; i < numVertices; i++) { + // the vertex belongs to the path, matrix rows + cstrs.clear(); + for (int j = 0; j < numVertices; j++) + cstrs.push_back(var(i, j, numVertices)); // (Xi0 || Xi1 || Xi2 ...) + clauses.push_back(cstrs); + + // the vertex appears just once in the path + for (int j = 0; j < numVertices; j++) { + for (int k = j + 1; k < numVertices; k++) + clauses.push_back({-var(i, j, numVertices), -var(i, k, numVertices)}); // ( !Xij && !Xik ) + } + + // each position in the path has a vertex, matrix cols + cstrs.clear(); + for (int j = 0; j < numVertices; j++) + cstrs.push_back(var(j, i, numVertices)); // (X0i || X1i || X2i ...) + clauses.push_back(cstrs); + + // each position has only 1 vertex + for (int j = 0; j < numVertices; j++) { + for (int k = j + 1; k < numVertices; k++) + clauses.push_back({-var(j, i, numVertices), -var(k, i, numVertices)}); // ( !Xji && !Xki ) + } + + // if there is no ij edje, there is no Xik Xj(k+1) or Xjk Xi(k+1) + for (int j = i + 1; j < numVertices; j++) { + // would be much faster with an adjacent matrix + bool found = false; + for (Edge e : edges) { + if ((e.from == i+1 && e.to == j+1) || (e.from == j+1 && e.to == i+1)) { + found = true; + break; + } + } + if (!found) { + // no v-w edge + for (int k = 0; k < (numVertices - 1); k++) { + clauses.push_back({-var(i, k, numVertices), -var(j, k + 1, numVertices)}); // ( !Xik && !Xj(k+1) + clauses.push_back({-var(j, k, numVertices), -var(i, k + 1, numVertices)}); // ( !Xjk && !Xi(k+1) + } + } + } + } + + cout << clauses.size() << " " << numVertices * numVertices << endl; + for (vector& c : clauses) { + for (int v : c) { + cout << v << " "; + } + cout << "0" << endl; + } + cout << endl; } }; diff --git a/05-advanced_algorithms_and_complexity/03-np-completness/03-budget_allocation/budget_allocation.cpp b/05-advanced_algorithms_and_complexity/03-np-completness/03-budget_allocation/budget_allocation.cpp index d2bfc51..c97937b 100644 --- a/05-advanced_algorithms_and_complexity/03-np-completness/03-budget_allocation/budget_allocation.cpp +++ b/05-advanced_algorithms_and_complexity/03-np-completness/03-budget_allocation/budget_allocation.cpp @@ -12,13 +12,58 @@ struct ConvertILPToSat { {} void printEquisatisfiableSatFormula() { - // This solution prints a simple satisfiable formula - // and passes about half of the tests. - // Change this function to solve the problem. - cout << "3 2" << endl; - cout << "1 2 0" << endl; - cout << "-1 -2 0" << endl; - cout << "1 -2 0" << endl; + int vars = A[0].size(); + int eqs = A.size(); + vector> clauses; + + // 5x1 + 2x2 + 3x3 ≤ 6 + // vector that are no solutions : (1,1,1)=10, (1,1,0)=7, (1,0,1)=8 + // corresponding clauses (!x || !y || !z), (!x || !y || z), (!x || y || !z) + vector coefficients(vars, -1); + for (int i = 0; i < eqs; i++) { + + vector equ = A[i]; + + // collect non 0 coefficients + coefficients.clear(); + for (int j = 0; j < vars; j++) { + if (equ[j] != 0) coefficients.push_back(j); + } + + vector clause; + // for each bit combinaison + for (int j = 0; j < (1< 0); + int w = coefficients[k]; + if (b) v += equ[w]; + w += 1; + clause.push_back(b ? -w: w); + } + + if (v > b[i]) { + clauses.push_back(clause); + } + } + } + + int n = clauses.size(); + if (n == 0) { + cout << "1 1\n1 -1 0"<< endl; + } else { + cout << clauses.size() << " " << vars << endl; + for (vector& c : clauses) { + for (int v : c) { + cout << v << " "; + } + cout << "0" << endl; + } + cout << endl; + } } }; -- cgit v1.1-2-g2b99