From 236f45435733d6c827a21b460b04e2cbf5c9e2cb Mon Sep 17 00:00:00 2001
From: Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz>
Date: Wed, 24 May 2023 22:46:13 +0200
Subject: [PATCH] =?UTF-8?q?Algoritmus=20pomoc=C3=AD=20semidefinitn=C3=ADho?=
 =?UTF-8?q?=20programov=C3=A1n=C3=AD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 algo/semidef_prog.cpp | 175 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 175 insertions(+)
 create mode 100644 algo/semidef_prog.cpp

diff --git a/algo/semidef_prog.cpp b/algo/semidef_prog.cpp
new file mode 100644
index 000000000..60d4b402b
--- /dev/null
+++ b/algo/semidef_prog.cpp
@@ -0,0 +1,175 @@
+#include "../main.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <cstring>
+#include <sdpa_call.h>
+#include <random>
+
+// ****** ARGS ********
+// <int>     number of tested cuts
+
+using std::pair;
+
+const int VERSION = 2;
+const bool ALLOW_MISTAKES = 0;
+
+template<class T>
+auto d2vec(int n, int m, T val=0)
+{
+	return vector<vector<T>>(n, vector<T>(m, val));
+}
+
+void printVector(vector<double> v, FILE * fpout)
+{
+		fprintf(fpout,"[ ");
+		for(auto jt:v)
+			fprintf(fpout,"%3d ",int(jt*100+0.5));
+		fprintf(fpout,"]; \n");
+}
+void printMatrix(vector<vector<double>> v, FILE * fpout)
+{
+	fprintf(fpout,"[\n");
+	for(auto it:v) printVector(it, fpout);
+	fprintf(fpout,"]; \n");
+}
+
+void printVector(vector<int> v, FILE * fpout)
+{
+		fprintf(fpout,"[ ");
+		for(auto jt:v)
+			fprintf(fpout,jt==0?" _ ":"%2d ", jt);
+		fprintf(fpout,"]; \n");
+}
+void printMatrix(vector<vector<int>> v, FILE * fpout)
+{
+	fprintf(fpout,"[\n");
+	for(auto it:v) printVector(it, fpout);
+	fprintf(fpout,"]; \n");
+}
+
+vector<bool> solve(int n, vector<int> input,
+		int argc, char const* const* argv)
+{
+	assert(argc==1);
+	int tested_cuts_count = atoi(argv[0]);
+	assert(tested_cuts_count > 0);
+
+	SDPA::printSDPAVersion(stderr);
+	SDPA sdpa;
+	sdpa.setDisplay(stderr);
+	sdpa.inputConstraintNumber(n);
+	sdpa.inputBlockNumber(1);
+	sdpa.inputBlockSize(1,n);
+	sdpa.inputBlockType(1,SDPA::SDP);
+
+	sdpa.initializeUpperTriangleSpace();
+
+	fo(i,n) sdpa.inputCVec(i+1, 1);
+	fo(i,n) sdpa.inputElement(i+1, 1, i+1, i+1,  1);
+
+	auto other = lib::gen_arr_other_car_of_type(n, input);
+
+	vector<vector<int> > c(n, vector<int>(n));
+	fo(i, 2*n-1)
+		c[input[i]][input[i+1]] += -1+2*((other[i]>i) == (other[i+1]>i+1));
+	fo(i,n) fo(j,i)
+		sdpa.inputElement(0, 1, 1+i, 1+j, c[i][j] + c[j][i]);
+
+
+	sdpa.initializeUpperTriangle();
+	sdpa.initializeSolve();
+
+	sdpa.solve();
+
+	auto m = d2vec<double>(n, n);
+	{
+		auto r = sdpa.getResultYMat(1);
+		fo(i,n) fo(j,n) m[i][j] = r[i*n + j];
+	}
+
+	//printMatrix(c, stderr);
+	//printMatrix(m, stderr);
+
+	auto sqrt_m = d2vec<double>(n, n);
+	fo(c, n)
+	{
+		{
+			double sum=0;
+			for(int i=c-1; i>=0; i--)
+				sum += sqrt_m[c][i] * sqrt_m[c][i];
+			sqrt_m[c][c] = sqrt(m[c][c] - sum);
+		}
+		for(int r=c+1; r<n; r++)
+		{
+			double sum=0;
+			for(int i=c-1; i>=0; i--)
+				sum += sqrt_m[r][i]*sqrt_m[c][i];
+			sqrt_m[r][c] = (m[r][c] - sum) / sqrt_m[c][c];
+		}
+	}
+	//printMatrix(sqrt_m, stderr);
+
+	vector<bool> out(2*n);
+
+	std::default_random_engine generator;
+	std::normal_distribution<double> distribution(0,1);
+
+	vector<double> rand_vector(n);
+
+	int best_score = 2*n; // +inf
+	fo(_, tested_cuts_count)
+	{
+		for (int i=0; i<n; ++i) {
+			rand_vector[i] = distribution(generator);
+		}
+		//printVector(rand_vector, stderr);
+
+		vector<double> multip(n);
+		fo(i,n) fo(j, n) multip[i] += sqrt_m[i][j]*rand_vector[j];
+		//printVector(multip, stderr);
+
+		vector<bool> current_out(2*n);
+		fo(i, 2*n)
+			current_out[i] = (other[i]>i) ^ (multip[input[i]]>=0);
+		int current_score=0;
+		fo(i, 2*n-1) current_score += current_out[i] != current_out[i+1];
+		if (current_score < best_score)
+		{
+			best_score = current_score;
+			out = current_out;
+		}
+	}
+
+	double val = 0;
+	double opt_score = 0;
+	double expected_score = 0;
+	fo(i,n) fo(j,n)
+	{
+		val += c[i][j] * m[i][j];
+	}
+	fo(i,2*n-1)
+	{
+		double scalar_product = m[input[i]][input[i+1]] * (-1+2*((other[i]>i) == (other[i+1]>i+1)));
+		if(scalar_product <-1) scalar_product =-1;
+		if(scalar_product > 1) scalar_product = 1;
+		double angle = acos(scalar_product);
+		double p = angle/M_PI;
+		//double opt_p = 0.5 - scalar_product/2;
+		// fprintf(stderr, "%3d: %3d %4d | %3d %3d\n", i, int(scalar_product*100+0.5), int(angle*100+0.5), int(p*100+0.5), int(opt_p*100+0.5));
+		expected_score += p;
+		//opt_score += opt_p;
+	}
+	lib::log_data("sdpa_primal_score", "%lf", sdpa.getPrimalObj());
+	lib::log_data("sdpa_dual_score", "%lf", sdpa.getDualObj());
+	//lib::log_data("opt_val", "%lf", 2*val);
+	//lib::log_data("opt_score", "%lf", opt_score);
+	lib::log_data("lower_bound", "%lf", (2*n-1)/2.0 - sdpa.getPrimalObj()/2/2);
+	lib::log_data("worst_case_score", "%lf", opt_score + 0.10527 * (2*n-1));
+	lib::log_data("expected_score", "%lf", expected_score);
+	fprintf(stderr, "opt_val: %lf\n", 2*val);
+	fprintf(stderr, "opt_score: %lf   %lf\n", (2*n-1 - val)/2, opt_score);
+	fprintf(stderr, "worst_case: %lf\n", opt_score + 0.10527 * (2*n-1));
+	fprintf(stderr, "expected_score: %lf\n", expected_score);
+
+	return out;
+}
-- 
GitLab