0
$\begingroup$

I made a random data matrix as

data = Table[Random[], {i, 5}, {j, 5}];

In my case it was $$ \left( \begin{array}{ccccc} 0.951203 & 0.546669 & 0.86928 & 0.00281753 & 0.306743 \\ 0.823344 & 0.117588 & 0.530483 & 0.777849 & 0.440718 \\ 0.109126 & 0.0686256 & 0.516334 & 0.460716 & 0.395735 \\ 0.254902 & 0.0376569 & 0.0648415 & 0.699014 & 0.373885 \\ 0.75997 & 0.995759 & 0.923424 & 0.498251 & 0.808767 \\ \end{array} \right)$$

I understand how Mathematica is able to solve the optimization problem below, thanks to the theory behind canonical correlation:

Minimize[
 Correlation[Sum[a[i] data[[;; , i]], {i, 1, 4}], data[[;; , -1]]], 
 Table[a[i], {i, 4}]]

What I am not sure is how is it possible to get an exact solution with Minimize when I add linear/affine constraints

Minimize[{Correlation[Sum[a[i] data[[;; , i]], {i, 1, 4}], 
   data[[;; , -1]]], a[1] + a[2] + a[3] + a[4] > 0.1, a[2] - a[3] < 1}, 
 Table[a[i], {i, 4}]]

I am interested to learn how Mathematica is doing the optimization under the hood for the constrained problem, because I would like to use the same method in Python for greater speed. Thanks.

$\endgroup$

1 Answer 1

1
$\begingroup$

Substitute some variables a[i] according to conditions with other variables b[i].

I rationalize data to get reliable conditions to show here.

data = Table[Random[], {i, 5}, {j, 5}] // Rationalize[#, 10^-5] &

data = {{254/763, 219/340, 83/85, 55/166, 260/383}, {50/183, 207/263, 67/135,
   179/380, 116/275}, {32/195, 46/205, 123/211, 95/251, 215/
  633}, {108/235, 747/971, 255/274, 271/376, 325/366}, {89/215, 99/
  223, 14/207, 124/407, 53/654}}

vars1 = Table[a[i], {i, 4}];

cor = Correlation[Sum[a[i] data[[;; , i]], {i, 1, 4}], 
           data[[;; , -1]]];

cond1 = a[1] + a[2] + a[3] + a[4] > 0.1 && a[2] - a[3] < 1 // 
           Rationalize

NMinimize[cor, vars1]

(*   {-1., {a[1] -> -31900.6, a[2] -> -8755.95, a[3] -> -57342.8, 
      a[4] -> -40593.6}}   *)

nmin1 = NMinimize[{cor, cond1}, vars1]

(*   {-0.835107, {a[1] -> 11.1137, a[2] -> -4.2961, a[3] -> -5.2961, 
                  a[4] -> -1.42148}}   *)

Conditions satisfied (sometimes other methods give better result)

cond1[[All, 1]] /. nmin1[[2]]

(*   0.1 && 1.   *)

NMinimize[{cor, cond1}, vars1, Method -> "SimulatedAnnealing"]

(*   {-0.835107, {a[1] -> 11.1131, a[2] -> -4.29585, a[3] -> -5.29585, 
  a[4] -> -1.42139}}   *)

Reduce condtions to solve for some varialbles.

Reduce[cond1, vars1, Reals]

(*   a[3] > -1 + a[2] && a[4] > 1/10 (1 - 10 a[1] - 10 a[2] - 10 a[3])   *)

My experience is, you get better results, if you alter the sequence of variables a[i] until you get one a[i] > ... and one a[j]< ...

Reduce[cond1, {a[4], a[3], a[2], a[1]}, Reals]

(*   a[2] < 1 + a[3] && a[1] > 1/10 (1 - 10 a[2] - 10 a[3] - 10 a[4])   *)

Now substitute b[i] with conditions b[i] > 0 or if you don't want to impose any condition on b[i] for calculation minimum with the phyton-minimization routine, substitute b[i]^2.

subst1 = {a[2] -> 1 + a[3] - b[2], 
          a[1] -> 1/10 (1 - 10 a[2] - 10 a[3] - 10 a[4]) + b[1]};

subst2 = {a[2] -> 1 + a[3] - b[2]^2, 
          a[1] -> 1/10 (1 - 10 a[2] - 10 a[3] - 10 a[4]) + b[1]^2};

Attention, substitute repeated with //. subst1

NMinimize[{cor //. subst1, b[1] > 0 && b[2] > 0}, {b[1], b[2], a[3], a[4]}]

(*   {-0.835107, {b[1] -> 0., b[2] -> 0., a[3] -> -5.29062, 
  a[4] -> -1.41992}}   *)

NMinimize[cor //. subst2, {b[1], b[2], a[3], a[4]}]

(*   {-0.835107, {b[1] -> -4.81865*10^-8, b[2] -> 7.9381*10^-7, 
  a[3] -> -5.29455, a[4] -> -1.42104}}   *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.