GET_SOLN Fetch solution values for specific named/indexed sets. VALS = OM.GET_SOLN(SET_TYPE, NAME) VALS = OM.GET_SOLN(SET_TYPE, NAME, IDX) VALS = OM.GET_SOLN(SET_TYPE, TAGS, NAME) VALS = OM.GET_SOLN(SET_TYPE, TAGS, NAME, IDX) Returns named/indexed results for a solved model, evaluated at the solution found. Inputs: SET_TYPE - one of the following, specifying the type of set: 'var' - variables 'lin' - linear constraints 'nle' - nonlinear equality constraints 'nli' - nonlinear inequality constraints 'nlc' - nonlinear costs 'qdc' - quadratic costs TAGS - char array or cell array of char arrays specifying the desired output(s). Valid tags vary by SET_TYPE as follows: 'var' - default is {'x', 'mu_l', 'mu_u'} 'x' - value of solution variable 'mu_l' - shadow price on variable lower bound 'mu_u' - shadow price on variable upper bound 'lin' - default is {'g', 'mu_l', 'mu_u'} 'g' - 1 x 2 cell array of upper and lower constraint values, {A*x - u, l - A*x} 'Ax_u' - upper constraint value, A*x - u 'l_Ax' - lower constraint value, l - A*x 'mu_l' - shadow price on constraint lower bound 'mu_u' - shadow price on constraint upper bound 'nle' - default is {'g', 'lam', 'dg'} 'g' - constraint value g(x) 'lam' - shadow price on constraint 'dg' - Jacobian of constraint 'nli' - default is {'h', 'mu', 'dh'} 'h' - constraint value h(x) 'mu' - shadow price on constraint 'dh' - Jacobian of constraint 'nlc' and 'qdc' - default is {'f', 'df', 'd2f'} 'f' - cost function value f(x) (for 'qdc' can return a vector) 'df' - gradient of cost function 'd2f' - Hessian of cost function NAME - char array specifying the name of the set IDX - cell array specifying the indices of the set Outputs: Variable number of outputs corresponding to TAGS input. If TAGS is empty or not specified, the calling context will define the number of outputs, returned in order of default tags for the specified SET_TYPE. Examples: [P, muPmin, muPmax] = om.get_soln('var', 'P'); [mu_u, mu_l] = om.get_soln('lin', {'mu_u', 'mu_l'}, 'lin_con_1'); dg_b_2_3 = om.get_soln('nle', 'dg', 'nle_con_b', {2,3}); For a complete set of solution vector values and shadow prices, using the PARSE_SOLN method may be more effecient. See also PARSE_SOLN.
0001 function varargout = get_soln(om, set_type, tags, name, idx) 0002 %GET_SOLN Fetch solution values for specific named/indexed sets. 0003 % VALS = OM.GET_SOLN(SET_TYPE, NAME) 0004 % VALS = OM.GET_SOLN(SET_TYPE, NAME, IDX) 0005 % VALS = OM.GET_SOLN(SET_TYPE, TAGS, NAME) 0006 % VALS = OM.GET_SOLN(SET_TYPE, TAGS, NAME, IDX) 0007 % 0008 % Returns named/indexed results for a solved model, evaluated at 0009 % the solution found. 0010 % 0011 % Inputs: 0012 % SET_TYPE - one of the following, specifying the type of set: 0013 % 'var' - variables 0014 % 'lin' - linear constraints 0015 % 'nle' - nonlinear equality constraints 0016 % 'nli' - nonlinear inequality constraints 0017 % 'nlc' - nonlinear costs 0018 % 'qdc' - quadratic costs 0019 % TAGS - char array or cell array of char arrays specifying the 0020 % desired output(s). Valid tags vary by SET_TYPE as follows: 0021 % 'var' - default is {'x', 'mu_l', 'mu_u'} 0022 % 'x' - value of solution variable 0023 % 'mu_l' - shadow price on variable lower bound 0024 % 'mu_u' - shadow price on variable upper bound 0025 % 'lin' - default is {'g', 'mu_l', 'mu_u'} 0026 % 'g' - 1 x 2 cell array of upper and lower constraint 0027 % values, {A*x - u, l - A*x} 0028 % 'Ax_u' - upper constraint value, A*x - u 0029 % 'l_Ax' - lower constraint value, l - A*x 0030 % 'mu_l' - shadow price on constraint lower bound 0031 % 'mu_u' - shadow price on constraint upper bound 0032 % 'nle' - default is {'g', 'lam', 'dg'} 0033 % 'g' - constraint value g(x) 0034 % 'lam' - shadow price on constraint 0035 % 'dg' - Jacobian of constraint 0036 % 'nli' - default is {'h', 'mu', 'dh'} 0037 % 'h' - constraint value h(x) 0038 % 'mu' - shadow price on constraint 0039 % 'dh' - Jacobian of constraint 0040 % 'nlc' and 'qdc' - default is {'f', 'df', 'd2f'} 0041 % 'f' - cost function value f(x) (for 'qdc' can return a vector) 0042 % 'df' - gradient of cost function 0043 % 'd2f' - Hessian of cost function 0044 % NAME - char array specifying the name of the set 0045 % IDX - cell array specifying the indices of the set 0046 % 0047 % Outputs: 0048 % Variable number of outputs corresponding to TAGS input. If TAGS 0049 % is empty or not specified, the calling context will define the 0050 % number of outputs, returned in order of default tags for the 0051 % specified SET_TYPE. 0052 % 0053 % Examples: 0054 % [P, muPmin, muPmax] = om.get_soln('var', 'P'); 0055 % [mu_u, mu_l] = om.get_soln('lin', {'mu_u', 'mu_l'}, 'lin_con_1'); 0056 % dg_b_2_3 = om.get_soln('nle', 'dg', 'nle_con_b', {2,3}); 0057 % 0058 % For a complete set of solution vector values and shadow prices, using 0059 % the PARSE_SOLN method may be more effecient. 0060 % 0061 % See also PARSE_SOLN. 0062 0063 % MP-Opt-Model 0064 % Copyright (c) 2020, Power Systems Engineering Research Center (PSERC) 0065 % by Ray Zimmerman, PSERC Cornell 0066 % 0067 % This file is part of MP-Opt-Model. 0068 % Covered by the 3-clause BSD License (see LICENSE file for details). 0069 % See https://github.com/MATPOWER/mp-opt-model for more info. 0070 0071 %% input arg handling 0072 if nargin == 3 %% om.get_soln(set_type, name) 0073 idx = []; 0074 name = tags; 0075 tags = {}; 0076 elseif nargin == 4 0077 if ischar(name) %% om.get_soln(set_type, tags, name) 0078 idx = []; 0079 else %% om.get_soln(set_type, name, idx) 0080 idx = name; 0081 name = tags; 0082 tags = {}; 0083 end 0084 end 0085 0086 %% set up tags for default outputs 0087 if isempty(tags) 0088 switch set_type 0089 case 'var' 0090 tags = {'x', 'mu_l', 'mu_u'}; 0091 case 'lin' 0092 if strcmp(om.problem_type(), 'LEQ') 0093 tags = {'f'}; %% 'Ax_u', 'l_Ax' are also options 0094 else 0095 tags = {'g', 'mu_l', 'mu_u'}; %% 'Ax_u', 'l_Ax' are also options 0096 end 0097 case 'nle' 0098 tags = {'g', 'lam', 'dg'}; 0099 case 'nli' 0100 tags = {'h', 'mu', 'dh'}; 0101 case 'nlc' 0102 tags = {'f', 'df', 'd2f'}; 0103 case 'qdc' 0104 tags = {'f', 'df', 'd2f'}; 0105 end 0106 elseif ~iscell(tags) 0107 tags = { tags }; 0108 end 0109 0110 %% set up indexing 0111 om_ff = om.(set_type); 0112 if isempty(idx) %% simple named set 0113 N = om_ff.idx.N.(name); 0114 i1 = om_ff.idx.i1.(name); %% starting row index 0115 iN = om_ff.idx.iN.(name); %% ending row index 0116 else %% indexed named set 0117 %% calls to substruct() are relatively expensive, so we pre-build the 0118 %% structs for addressing cell and numeric array fields, updating only 0119 %% the subscripts before use 0120 sc = struct('type', {'.', '{}'}, 'subs', {name, idx}); %% cell array field 0121 sn = sc; sn(2).type = '()'; %% num array field 0122 N = subsref(om_ff.idx.N, sn); 0123 i1 = subsref(om_ff.idx.i1, sn); %% starting row index 0124 iN = subsref(om_ff.idx.iN, sn); %% ending row index 0125 end 0126 0127 %% get outputs 0128 varargout = cell(1, nargout); 0129 s = om.soln; 0130 if N && ~isempty(s.eflag) 0131 switch set_type 0132 case 'var' 0133 for k = 1:nargout 0134 switch tags{k} 0135 case 'x' 0136 varargout{k} = s.x(i1:iN); 0137 case 'mu_l' 0138 varargout{k} = s.lambda.lower(i1:iN); 0139 case 'mu_u' 0140 varargout{k} = s.lambda.upper(i1:iN); 0141 otherwise 0142 error('opt_model/get_soln: unknown tag ''%s''', tags{k}); 0143 end 0144 end 0145 case 'lin' 0146 if strcmp(om.problem_type(), 'LEQ') %% tag must be 'f' 0147 varargout{1} = s.f(i1:iN); 0148 else 0149 if any(ismember({'g', 'Ax_u', 'l_Ax'}, tags(1:nargout))) 0150 g = cell(1,2); 0151 [g{:}] = om.eval_lin_constraint(s.x, name, idx); 0152 end 0153 for k = 1:nargout 0154 switch tags{k} 0155 case 'g' 0156 varargout{k} = g; 0157 case 'Ax_u' 0158 varargout{k} = g{1}; 0159 case 'l_Ax' 0160 varargout{k} = g{2}; 0161 case 'mu_l' 0162 varargout{k} = s.lambda.mu_l(i1:iN); 0163 case 'mu_u' 0164 varargout{k} = s.lambda.mu_u(i1:iN); 0165 otherwise 0166 error('opt_model/get_soln: unknown tag ''%s''', tags{k}); 0167 end 0168 end 0169 end 0170 case 'nle' 0171 if ismember('dg', tags(1:nargout)) 0172 [g, dg] = om.eval_nln_constraint(s.x, 1, name, idx); 0173 elseif ismember('g', tags(1:nargout)) 0174 g = om.eval_nln_constraint(s.x, 1, name, idx); 0175 end 0176 for k = 1:nargout 0177 switch tags{k} 0178 case 'g' 0179 varargout{k} = g; 0180 case 'dg' 0181 varargout{k} = dg; 0182 case 'lam' 0183 varargout{k} = s.lambda.eqnonlin(i1:iN); 0184 otherwise 0185 error('opt_model/get_soln: unknown tag ''%s''', tags{k}); 0186 end 0187 end 0188 case 'nli' 0189 if ismember('dh', tags(1:nargout)) 0190 [h, dh] = om.eval_nln_constraint(s.x, 0, name, idx); 0191 elseif ismember('h', tags(1:nargout)) 0192 h = om.eval_nln_constraint(s.x, 0, name, idx); 0193 end 0194 for k = 1:nargout 0195 switch tags{k} 0196 case 'h' 0197 varargout{k} = h; 0198 case 'dh' 0199 varargout{k} = dh; 0200 case 'mu' 0201 varargout{k} = s.lambda.ineqnonlin(i1:iN); 0202 otherwise 0203 error('opt_model/get_soln: unknown tag ''%s''', tags{k}); 0204 end 0205 end 0206 case 'nlc' 0207 if ismember('d2f', tags(1:nargout)) 0208 [f, df, d2f] = om.eval_nln_cost(s.x, name, idx); 0209 elseif ismember('df', tags(1:nargout)) 0210 [f, df] = om.eval_nln_cost(s.x, name, idx); 0211 else 0212 f = om.eval_nln_cost(s.x, name, idx); 0213 end 0214 for k = 1:nargout 0215 switch tags{k} 0216 case 'f' 0217 varargout{k} = f; 0218 case 'df' 0219 varargout{k} = df; 0220 case 'd2f' 0221 varargout{k} = d2f; 0222 otherwise 0223 error('opt_model/get_soln: unknown tag ''%s''', tags{k}); 0224 end 0225 end 0226 case 'qdc' 0227 if ismember('d2f', tags(1:nargout)) 0228 [f, df, d2f] = om.eval_quad_cost(s.x, name, idx); 0229 elseif ismember('df', tags(1:nargout)) 0230 [f, df] = om.eval_quad_cost(s.x, name, idx); 0231 else 0232 f = om.eval_quad_cost(s.x, name, idx); 0233 end 0234 for k = 1:nargout 0235 switch tags{k} 0236 case 'f' 0237 varargout{k} = f; 0238 case 'df' 0239 varargout{k} = df; 0240 case 'd2f' 0241 varargout{k} = d2f; 0242 otherwise 0243 error('opt_model/get_soln: unknown tag ''%s''', tags{k}); 0244 end 0245 end 0246 otherwise 0247 error('opt_model/get_soln: unknown set_type ''%s''', set_type); 0248 end %% switch set_type 0249 end 0250 end %% if N