PageRenderTime 52ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/cvx/builtins/@cvx/times.m

http://github.com/tcdoan/portfolioOptimization
Objective C | 294 lines | 259 code | 35 blank | 0 comment | 54 complexity | 29c064cdd081dd160f639ecf155cd6e9 MD5 | raw file
Possible License(s): GPL-2.0
  1. function z = times( x, y, oper )
  2. % Disciplined convex programming information for TIMES:
  3. % In general, disciplined convex programs must obey the "no-product
  4. % rule" which states that two non-constant expressions cannot be
  5. % multiplied together. Under this rule, the following combinations
  6. % are allowed:
  7. % {constant} .* {non-constant} {non-constant} .* {constant}
  8. % Furthermore, if the non-constant expression is nonlinear, then
  9. % the constant term must be real.
  10. %
  11. % A lone exception to the no-product rule is made for quadratic
  12. % forms: two affine expressions may be multiplied together if the
  13. % result is convex or concave. For example, the construction
  14. % variable x(n)
  15. % x.*x <= 1;
  16. % would be permitted because each element of x.*x is convex.
  17. %
  18. % Disciplined geometric programming information for TIMES:
  19. % Both terms in a multiplication must have the same log-curvature,
  20. % so the following products are permitted:
  21. % {log-convex} .* {log-convex} {log-concave} .* {log-concave}
  22. % {log-affine} .* {log-affine}
  23. % Note that log-affine expressions are both log-convex and
  24. % log-concave.
  25. %
  26. % For vectors, matrices, and arrays, these rules are verified
  27. % indepdently for each element.
  28. error( nargchk( 2, 3, nargin ) );
  29. if nargin < 3, oper = '.*'; end
  30. %
  31. % Check sizes
  32. %
  33. sx = size( x );
  34. sy = size( y );
  35. xs = all( sx == 1 );
  36. ys = all( sy == 1 );
  37. if xs,
  38. sz = sy;
  39. elseif ys,
  40. sz = sx;
  41. elseif ~isequal( sx, sy ),
  42. error( 'Matrix dimensions must agree.' );
  43. else
  44. sz = sx;
  45. end
  46. nn = prod( sz );
  47. if nn == 0,
  48. z = zeros( sz );
  49. return
  50. end
  51. %
  52. % Determine the computation methods
  53. %
  54. persistent remap_m remap_l remap_r
  55. if isempty( remap_r ),
  56. % zero .* valid, valid .* zero, constant .* constant
  57. temp_1 = cvx_remap( 'constant' );
  58. temp_2 = cvx_remap( 'zero' );
  59. temp_3 = temp_2' * cvx_remap( 'valid' );
  60. remap_1 = ( temp_1' * temp_1 ) | temp_3 | temp_3';
  61. remap_1n = ~remap_1;
  62. % constant / nonzero, zero / log-concave, zero / log-convex
  63. temp_4 = temp_1 & ~temp_2;
  64. remap_1r = ( temp_1' * temp_4 ) | ( temp_2' * cvx_remap( 'log-valid' ) );
  65. remap_1rn = ~remap_1r;
  66. % constant * affine, real * convex/concave/log-convex, positive * log-concave
  67. temp_5 = cvx_remap( 'real' );
  68. temp_6 = cvx_remap( 'positive' );
  69. temp_7 = cvx_remap( 'affine' );
  70. temp_1n = ~temp_1;
  71. temp_8 = cvx_remap( 'log-concave' ) & temp_1n;
  72. remap_2 = ( temp_1' * temp_7 ) | ...
  73. ( temp_5' * cvx_remap( 'convex', 'concave', 'log-convex' ) ) | ...
  74. ( temp_6' * temp_8 );
  75. remap_2 = remap_2 & remap_1n;
  76. % real / log-concave, positive / log-convex
  77. temp_9 = cvx_remap( 'log-convex' ) & temp_1n;
  78. remap_2r = ( temp_5' * temp_8 ) | ...
  79. ( temp_6' * temp_9 );
  80. remap_2r = remap_2r & remap_1rn;
  81. % Affine * constant, convex/concave/log-convex * real, log-concave * positive
  82. remap_3 = remap_2';
  83. % Affine / nonzero, convex/concave/log-convex / nzreal, log-concave / positive
  84. remap_3r = remap_3;
  85. remap_3r(:,2) = 0;
  86. % Affine * affine
  87. remap_4 = temp_7 & ~temp_1;
  88. remap_4 = remap_4' * +remap_4;
  89. % log-concave * log-concave, log-convex * log-convex
  90. remap_5 = ( temp_8' * +temp_8 ) | ( temp_9' * +temp_9 );
  91. % log-concave / log-convex, log-convex / log-concave
  92. remap_5r = temp_8' * +temp_9;
  93. remap_5r = remap_5r | remap_5r';
  94. remap_m = remap_1 + 2 * remap_2 + 3 * remap_3 + 4 * remap_4 + 5 * remap_5;
  95. remap_r = remap_1r + 2 * remap_2r + 3 * remap_3r + 5 * remap_5r;
  96. remap_r(:,2) = 0;
  97. remap_l = remap_r';
  98. end
  99. switch oper,
  100. case '.*',
  101. remap = remap_m;
  102. r_recip = 0;
  103. l_recip = 0;
  104. case './',
  105. remap = remap_r;
  106. r_recip = 1;
  107. l_recip = 0;
  108. case '.\',
  109. remap = remap_l;
  110. r_recip = 0;
  111. l_recip = 1;
  112. end
  113. vx = cvx_classify( x );
  114. vy = cvx_classify( y );
  115. vr = remap( vx + size( remap, 1 ) * ( vy - 1 ) );
  116. vu = sort( vr(:) );
  117. vu = vu([true;diff(vu)~=0]);
  118. nv = length( vu );
  119. if vu(1) == 1 && nv > 1,
  120. vr(vr==1) == vu(2);
  121. nv = nv - 1;
  122. vu(1) = [];
  123. end
  124. %
  125. % Process each computation type separately
  126. %
  127. x = cvx( x );
  128. y = cvx( y );
  129. xt = x;
  130. yt = y;
  131. if nv ~= 1,
  132. z = cvx( sz, [] );
  133. end
  134. for k = 1 : nv,
  135. %
  136. % Select the category of expression to compute
  137. %
  138. if nv ~= 1,
  139. t = vr == vu( k );
  140. if ~xs,
  141. xt = cvx_subsref( x, t );
  142. sz = size( xt );
  143. end
  144. if ~ys,
  145. yt = cvx_subsref( y, t );
  146. sz = size( yt );
  147. end
  148. end
  149. %
  150. % Apply the appropriate computation
  151. %
  152. switch vu( k ),
  153. case 0,
  154. % Invalid
  155. error( 'Disciplined convex programming error:\n Cannot perform the operation: {%s} %s {%s}', cvx_class( xt, true, true, true ), oper, cvx_class( yt, true, true, true ) );
  156. case 1,
  157. % constant .* constant
  158. xb = cvx_constant( xt );
  159. yb = cvx_constant( yt );
  160. if l_recip,
  161. cvx_optval = xb .\ yb;
  162. elseif r_recip,
  163. cvx_optval = xb ./ yb;
  164. else
  165. cvx_optval = xb .* yb;
  166. end
  167. if nnz( isnan( cvx_optval ) ),
  168. error( 'Disciplined convex programming error:\n This expression produced one or more invalid numeric values (NaNs).', 1 ); %#ok
  169. end
  170. cvx_optval = cvx( cvx_optval );
  171. case 2,
  172. % constant .* something
  173. xb = cvx_constant( xt );
  174. if l_recip, xb = 1.0 ./ xb; end
  175. yb = yt;
  176. if r_recip && nnz( xb ), yb = exp( - log( yb ) ); end
  177. yb = yb.basis_;
  178. if ~xs,
  179. nn = numel( xb );
  180. if ys,
  181. xb = cvx_reshape( xb, [ 1, nn ] );
  182. if issparse( yb ) && ~issparse( xb ),
  183. xb = sparse( xb );
  184. end
  185. else
  186. n1 = 1 : nn;
  187. xb = sparse( n1, n1, xb( : ), nn, nn );
  188. end
  189. end
  190. cvx_optval = cvx( sz, yb * xb );
  191. case 3,
  192. % something .* constant
  193. yb = cvx_constant( yt );
  194. if r_recip, yb = 1.0 ./ yb; end
  195. xb = xt;
  196. if l_recip && any( xb ), xb = exp( - log( xb ) ); end
  197. xb = xb.basis_;
  198. if ~ys,
  199. nn = numel( yb );
  200. if xs,
  201. yb = cvx_reshape( yb, [ 1, nn ] );
  202. if issparse( xb ) && ~issparse( yb ),
  203. yb = sparse( yb );
  204. end
  205. else
  206. n1 = 1 : nn;
  207. yb = sparse( n1, n1, yb( : ), nn, nn );
  208. end
  209. end
  210. cvx_optval = cvx( sz, xb * yb );
  211. case 4,
  212. % affine .* affine
  213. nn = prod( sz );
  214. xA = xt.basis_; yA = yt.basis_;
  215. if xs && ~ys, xA = xA( :, ones( 1, nn ) ); end
  216. if ys && ~xs, yA = yA( :, ones( 1, nn ) ); end
  217. mm = max( size( xA, 1 ), size( yA, 1 ) );
  218. if size( xA, 1 ) < mm, xA( mm, end ) = 0; end
  219. if size( yA, 1 ) < mm, yA( mm, end ) = 0; end
  220. xB = xA( 1, : ); xA( 1, : ) = 0;
  221. yB = yA( 1, : ); yA( 1, : ) = 0;
  222. cyA = conj( yA );
  223. alpha = sum( real( xA .* yA ), 1 ) ./ max( sum( cyA .* yA, 1 ), realmin );
  224. adiag = sparse( 1 : nn, 1 : nn, alpha, nn, nn );
  225. if all( sum( abs( xA - cyA * adiag ), 2 ) <= 2 * eps * sum( abs( xA ), 2 ) ),
  226. beta = xB - alpha .* conj( yB );
  227. alpha = reshape( alpha, sz );
  228. if isreal( y ),
  229. cvx_optval = alpha .* square( y ) + reshape( beta, sz ) .* y;
  230. elseif all( abs( beta ) <= 2 * eps * abs( xB ) ),
  231. cvx_optval = alpha .* square_abs( y );
  232. else
  233. error( 'Disciplined convex programming error:\n Invalid quadratic form(s): product is not real.\n', 1 ); %#ok
  234. end
  235. else
  236. error( 'Disciplined convex programming error:\n Invalid quadratic form(s): not a square.\n', 1 ); %#ok
  237. end
  238. case 5,
  239. % posynomial .* posynomial
  240. xb = log( xt );
  241. if l_recip, xb = - xb; end
  242. yb = log( yt );
  243. if r_recip, yb = - yb; end
  244. cvx_optval = exp( xb + yb );
  245. otherwise,
  246. error( 'Shouldn''t be here.' );
  247. end
  248. %
  249. % Store the results
  250. %
  251. if nv == 1,
  252. z = cvx_optval;
  253. else
  254. z = cvx_subsasgn( z, t, cvx_optval );
  255. end
  256. end
  257. % Copyright 2010 Michael C. Grant and Stephen P. Boyd.
  258. % See the file COPYING.txt for full copyright information.
  259. % The command 'cvx_where' will show where this file is located.