idol
A C++ Framework for Optimization
Loading...
Searching...
No Matches
to_rotated_quadratic_cone.h
1//
2// Created by henri on 22/02/23.
3//
4
5#ifndef IDOL_TO_ROTATED_QUADRATIC_CONE_H
6#define IDOL_TO_ROTATED_QUADRATIC_CONE_H
7
8#ifdef IDOL_USE_EIGEN
9
10#include "idol/mixed-integer/modeling/expressions/LinExpr.h"
11#include "SquareMatrix.h"
12
13namespace idol {
14
15 /*
16 static std::list<AffExpr<Var>> to_rotated_quadratic_cone(const QuadExpr<Var> &t_expr) {
17
18 // Create index mapping
19 MatrixIndices indices;
20
21 for (const auto &[vars, constant]: t_expr) {
22 indices.add(vars.first);
23 indices.add(vars.second);
24 }
25
26 // Create quadratic form matrix s.t. quadratic_part = x^TQx
27 SquareMatrix Q(indices);
28
29 for (const auto &[vars, constant]: t_expr) {
30 if (vars.first.id() == vars.second.id()) {
31 Q.set(vars.first, vars.second, constant);
32 } else {
33 Q.set(vars.first, vars.second, constant / 2.);
34 }
35 }
36
37 // Compute Q = LDL^T decomposition
38 const auto &[L, D] = Q.eigen_decomposition();
39
40 // Search for negative eigen values
41 std::list<std::pair<Var, double>> negative_eigen_values;
42 for (const auto &[var, index]: indices.indices()) {
43 const double eigen_value = D.get(index, index);
44 if (eigen_value < 0) {
45 negative_eigen_values.emplace_back(var, eigen_value);
46 }
47 }
48
49 const unsigned int n_negative_eigen_values = negative_eigen_values.size();
50
51 if (n_negative_eigen_values > 2) {
52 throw Exception("Non-convex expression found.");
53 }
54
55 // We write x^TQx = ||Fx||^2 + x^TNx
56
57 // Compute F = sqrt( D - D^- )L^T where D^- is D without negative entries
58 auto F = D;
59 for (const auto &[var, eigen_value]: negative_eigen_values) {
60 F.set(var, var, 0);
61 }
62 F = F.sqrt() * L.transpose();
63
64 // Compute N = LD^-L^T
65 SquareMatrix N(indices);
66 for (const auto &[var, eigen_value]: negative_eigen_values) {
67 N.set(var, var, eigen_value);
68 }
69 N = L * N * L.transpose();
70
71 // Build result
72 std::list<AffExpr<Var>> result;
73
74 // Create head
75 for (const auto &[var1, i]: indices.indices()) {
76 LinExpr<Var> expr;
77 for (const auto &[var2, j]: indices.indices()) {
78 const double n_ij = N.get(i, j);
79 if (n_ij == 0) { continue; }
80 expr += LinExpr<Var>(std::sqrt(-n_ij), var2);
81 }
82 if (!expr.empty()) {
83 result.emplace_back(std::move(expr));
84 }
85 }
86
87 if (result.empty()) {
88 result.emplace_back();
89 result.emplace_back();
90 }
91
92 if (result.size() == 1) {
93 result.emplace_back(result.front());
94 }
95
96 result.front() *= .5;
97
98 if (result.size() > 2) {
99 throw Exception("Non-convex expression found.");
100 }
101
102 for (const auto &[_, i]: indices.indices()) {
103
104 LinExpr<Var> expr;
105 for (const auto &[var, j]: indices.indices()) {
106 expr += LinExpr<Var>(F.get(i, j), var);
107 }
108
109 if (!expr.empty()) {
110 result.emplace_back(std::move(expr));
111 }
112 }
113
114 return result;
115 }
116 */
117}
118
119#endif
120
121#endif //IDOL_TO_ROTATED_QUADRATIC_CONE_H