|
| 1 | +function [params_out,fval,p_opt,union_y_a,idzActive] = priv_conform_iterOD(sys, params, options) |
| 2 | +% priv_conform_iterOD - conformance synthesis with iterative outlier |
| 3 | +% detection based on [1] |
| 4 | +% |
| 5 | +% Syntax: |
| 6 | +% [params_out, results] = priv_conform_iterOD(pred, params, options) |
| 7 | +% |
| 8 | +% Inputs: |
| 9 | +% pred - confPredictor object |
| 10 | +% params - Initial test parameters, including the test suite |
| 11 | +% options - options for conformance synthesis |
| 12 | +% |
| 13 | +% Outputs: |
| 14 | +% params_out - parameters solving the conformance problem |
| 15 | +% fval - conformance cost |
| 16 | +% p_opt - estimated parameters containing the scaling factors alpha |
| 17 | +% and the change of the center vectors Delta c with |
| 18 | +% p_opt = [alpha_x' alpha_u' dc_x' dc_u']' |
| 19 | +% union_y_a - n_m x 1 cell array with dim_y x n_k x n_s output arrays |
| 20 | +% with union_y_a{m} = testSuite(m).y - y_nom |
| 21 | +% m_active - indizes of active data points at the final solution |
| 22 | +% |
| 23 | +% References: |
| 24 | +% [1] Campi et al. 2009, "Interval predictor models: Identification and |
| 25 | +% reliability". |
| 26 | +% [2] Laura Luetzow, Michael Eichelbeck, Mykel Kochenderfer, and |
| 27 | +% Matthias Althoff. "Zono-Conformal Prediction: Zonotope-Based |
| 28 | +% Uncertainty Quantification for Regression and Classification |
| 29 | +% Tasks," arXiv, 2025. |
| 30 | +% |
| 31 | +% Other m-files required: none |
| 32 | +% Subfunctions: none |
| 33 | +% MAT-files required: none |
| 34 | +% |
| 35 | +% See also: confPredictor |
| 36 | + |
| 37 | +% Authors: Michael Eichelbeck, Laura Luetzow |
| 38 | +% Written: 02-October-2025 |
| 39 | +% Last update: --- |
| 40 | +% Last revision: --- |
| 41 | + |
| 42 | +% ------------------------------ BEGIN CODE ------------------------------- |
| 43 | + |
| 44 | +if strcmp(options.cs.outMethod,'searchG') |
| 45 | + greedy = true; |
| 46 | +else |
| 47 | + greedy = false; % Default to non-greedy approach if not specified |
| 48 | +end |
| 49 | +n_out = options.cs.numOutlier; |
| 50 | + |
| 51 | +num_nodes = zeros(n_out+1, 1); % Stores the number of nodes at each level of the search tree |
| 52 | + |
| 53 | +% Data structures to store intermediate results during constraint removal |
| 54 | +idxConstr = cell(n_out+1, 1); % Stores reduced test suites at each level of the search tree |
| 55 | +fval_all = zeros(n_out+1, 1); % Tracks the cost function values at each level |
| 56 | +fval_best = zeros(n_out+1, 1); % Tracks the cost function values at each level |
| 57 | +params_best = cell(n_out+1,1); |
| 58 | +T_all = zeros(n_out+1, 1); |
| 59 | +resOut = cell(n_out, 1); % Stores results for each node in the search tree |
| 60 | + |
| 61 | +idxConstr{1,1} = 1:length(params.testSuite); |
| 62 | +m_constr = idxConstr{1,1}; % Initialize root node using all test cases |
| 63 | +options.cs.idzOutlier = []; |
| 64 | +num_nodes(1) = 1; % Root level has a single node |
| 65 | + |
| 66 | +% Initial run with all constraints active to determine baseline performance |
| 67 | +options.cs.determineActive = true; |
| 68 | +options.cs.numOutlier = length(options.cs.idzOutlier); |
| 69 | +Timer = tic; |
| 70 | +[params_out,fval,p_opt,union_y_a,idzActive] = priv_conform_white(sys,params,options); |
| 71 | +results.sys = sys; |
| 72 | +results.unifiedOutputs = union_y_a; |
| 73 | +results.idzActive = idzActive; |
| 74 | +results.fval = fval; |
| 75 | +results.p = p_opt; |
| 76 | +T_all(1) = toc(Timer); |
| 77 | +resOut{1,1} = struct('params', params_out, 'results', results); |
| 78 | +fval_all(1,1) = results.fval; % Store initial cost function value |
| 79 | +fval_best(1,1) = results.fval; |
| 80 | +params_best{1} = params_out; |
| 81 | +correctPred = false; |
| 82 | + |
| 83 | +if fval == 0 |
| 84 | + % all predictions are already correct, removal of additional data |
| 85 | + % points does not imrpove the cost |
| 86 | + return |
| 87 | +end |
| 88 | + |
| 89 | +% Begin search tree traversal to remove constraints |
| 90 | +for i=1:n_out % Iterate over each level of the tree (corresponding to outlier removals) |
| 91 | + num_nodes(i+1) = 0; % Initialize node count for the next level |
| 92 | + best_fval = Inf; % Track best fval for greedy selection |
| 93 | + best_idx_constr = []; |
| 94 | + best_results = []; |
| 95 | + if correctPred |
| 96 | + % copy results of previous level if all predictions are already correct |
| 97 | + num_nodes(i+1) = num_nodes(i+1) + 1; % Increment node count for next level |
| 98 | + idxConstr{i+1, num_nodes(i+1)} = m_constr; % Store the updated test suite |
| 99 | + fval_all(i+1, num_nodes(i+1)) = fval_l; % Store the updated cost function value |
| 100 | + resOut{i+1,num_nodes(i+1)} = struct('params', paramsRes_l, 'results', results_l); |
| 101 | + continue |
| 102 | + end |
| 103 | + |
| 104 | + for h=1:num_nodes(i) % Iterate over each node at the current level |
| 105 | + if correctPred |
| 106 | + % cancel loop if all predictions are correct |
| 107 | + break |
| 108 | + end |
| 109 | + active_constraints = resOut{i, h}.results.idzActive; % Identify active constraints |
| 110 | + for l=1:length(active_constraints) % Iterate through active constraints |
| 111 | + c_index = active_constraints(l); |
| 112 | + % Remove the selected constraint from the parent node's test suite |
| 113 | + m_constr = idxConstr{i,h}; |
| 114 | + m_constr(c_index) = []; |
| 115 | + |
| 116 | + % Evaluate the modified parameter set |
| 117 | + options.cs.idzOutlier = 1:length(params.testSuite); |
| 118 | + options.cs.idzOutlier(m_constr) = []; |
| 119 | + options.cs.numOutlier = length(options.cs.idzOutlier); |
| 120 | + |
| 121 | + [paramsRes_l,fval_l,p_opt,union_y_a,idzActive] = priv_conform_white(sys,params,options); |
| 122 | + results_l.sys = sys; |
| 123 | + results_l.unifiedOutputs = union_y_a; |
| 124 | + results_l.idzActive = idzActive; |
| 125 | + results_l.fval = fval_l; |
| 126 | + results_l.p = p_opt; |
| 127 | + |
| 128 | + if greedy % Greedy approach: only keep track of the best option at each level |
| 129 | + if fval_l <= best_fval |
| 130 | + best_fval = fval_l; |
| 131 | + best_idx_constr = m_constr; |
| 132 | + best_results = results_l; |
| 133 | + best_params = paramsRes_l; |
| 134 | + |
| 135 | + end |
| 136 | + else % Non-greedy approach: explore all possible nodes |
| 137 | + if (fval_l <= fval_all(i,h)) % If the new result improves the cost function |
| 138 | + % Consider the removed constraint as a support constraint and create a new node |
| 139 | + num_nodes(i+1) = num_nodes(i+1) + 1; % Increment node count for next level |
| 140 | + idxConstr{i+1, num_nodes(i+1)} = m_constr; % Store the updated test suite |
| 141 | + fval_all(i+1, num_nodes(i+1)) = fval_l; % Store the updated cost function value |
| 142 | + resOut{i+1,num_nodes(i+1)} = struct('params', paramsRes_l, 'results', results_l); |
| 143 | + end |
| 144 | + end |
| 145 | + if fval_l == 0 |
| 146 | + correctPred = true; |
| 147 | + % no uncertainty in the point predictions |
| 148 | + break |
| 149 | + end |
| 150 | + end |
| 151 | + end |
| 152 | + |
| 153 | + if greedy % If using greedy search, only keep the best node and discard others |
| 154 | + if ~isempty(best_idx_constr) |
| 155 | + num_nodes(i+1) = 1; |
| 156 | + idxConstr{i+1,1} = best_idx_constr; |
| 157 | + fval_all(i+1,1) = best_fval; |
| 158 | + resOut{i+1,1} = struct('params', best_params, 'results', best_results); |
| 159 | + end |
| 160 | + end |
| 161 | + T_all(i+1) = toc(Timer); |
| 162 | + [fval_best(i+1), idx] = min(fval_all(i+1,:),[],2); |
| 163 | + params_best{i+1} = resOut{i+1,idx}.params; |
| 164 | +end |
| 165 | + |
| 166 | +% Identify the best result in the last level of the search tree |
| 167 | +for j=1:num_nodes(n_out+1) |
| 168 | + if resOut{n_out+1,j}.results.fval < results.fval % Check if a better result is found |
| 169 | + results = resOut{n_out+1,j}.results; |
| 170 | + params_out = resOut{n_out+1,j}.params; |
| 171 | + end |
| 172 | +end |
| 173 | +fval = results.fval; |
| 174 | +p_opt = results.p; |
| 175 | +union_y_a = results.unifiedOutputs; |
| 176 | +idzActive = results.idzActive; |
| 177 | + |
| 178 | +end |
| 179 | + |
| 180 | +% ------------------------------ END OF CODE ------------------------------ |
0 commit comments