diff --git a/.gitignore b/.gitignore index 45c38d6d..def1019e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ Ext/ModelsData fileServerFolder docrun_backup.mat *.exe +!wordgen.exe *.r2015a *_ert_rtw *.7z diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bca0b30..c16a9640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# Release 1.11.4 +- BreachProblemGui improvements +- Added SDToolbox (Sigma-Delta) and example +- Reorganized and fixed wordgen support +- Set_t0 method for BreachRequirement + +## Minor +- param_gen now checks output parameters when they are changed +- BreachRequirement display requirements names +- BreachRequirement checks if STL file exists when reading from a file +- fixed bug with traj.time when reading from disk cache +- waitbar for parSim + # Release 1.11.3 - Fix BreachSamplesPlot data tip 3D bug - Improved BreachProblemGui diff --git a/Core/Algos/@BreachProblem/BreachProblem.m b/Core/Algos/@BreachProblem/BreachProblem.m index 93e55c28..b4f79f30 100644 --- a/Core/Algos/@BreachProblem/BreachProblem.m +++ b/Core/Algos/@BreachProblem/BreachProblem.m @@ -1,7 +1,7 @@ classdef BreachProblem < BreachStatus % BreachProblem A class for generic optimization problem involving STL specifications % - % A BreachProblem is essentially created from a BreachSystem and a + % A BreachProblem is essentially created from a BreachSet orBreachSystem and a % property. E.g., % % problem = BreachProblem(BrSys, phi); @@ -33,7 +33,6 @@ % (often translates into number of simulations of % system under test) % log_traces - (default=true) logs all traces computed during optimization - % T_spec - time % % BreachProblem Properties (outputs) % BrSet_Logged - BreachSet with parameter vectors used during optimization. @@ -62,6 +61,7 @@ x0 solver= 'global_nelder_mead' % default solver name solver_options % solver options + Spec % BreachRequirement object reset to R0 for each objective evaluation T_Spec=0 @@ -254,9 +254,11 @@ function ResetObjective(this, BrSet, params, ranges) this.BrSet = BrSet.copy(); end - this.BrSet.Sys.Verbose=0; this.BrSet.verbose = 0; - + if isa(BrSet,'BreachSystem') + this.BrSet.Sys.Verbose=0; + end + % Parameter ranges if ~exist('params','var') [params, ipr] = this.BrSet.GetBoundedDomains(); @@ -291,14 +293,14 @@ function ResetObjective(this, BrSet, params, ranges) % robustness this.BrSys = this.BrSet.copy(); - this.BrSys.SetParam(this.params, this.x0(:,1), 'spec'); [~, ia] = unique( this.BrSys.P.pts','rows'); if numel(ia)= this.max_time) ||... (this.nb_obj_eval>= this.max_obj_eval) || ... @@ -1275,7 +1277,8 @@ function LogX(this, x, fval, cval, x_stoch) end end end - + + function [BrOut, Berr, BbadU] = GetBrSet_Logged(this) % GetBrSet_Logged gets BreachSet object containing parameters and traces computed during optimization BrOut = this.BrSet_Logged; @@ -1346,6 +1349,16 @@ function LogX(this, x, fval, cval, x_stoch) Rbest = this.GetBrSet_Best(varargin{:}); end + function B = GetBrSet_ObjLog(this) + B = []; + if ~isempty(this.X_log) + B = BreachSet([this.params 'obj']); + B.SetParam(this.params, this.X_log); + B.SetParam('obj', this.obj_log); + end + + end + %% Display functions function Display_X(this, param_values) @@ -1404,7 +1417,30 @@ function Display_Best_Results(this, best_fval, param_values) end end - + + function plot_obj_scatter_heat(this, params) + + if nargin==1 + idx_params = 1:2; + params = this.params(1:2); + elseif isnumeric(params) + idx_params = params; + params = this.params(idx_params); + end + + if numel(idx_params)==2 % 2d plot + x = this.X_log(idx_params(1),:); + y = this.X_log(idx_params(2),:); + c = this.obj_log; + scatter_heat(x,y,c); + end + + xlabel(this.params{idx_params(1)}); + ylabel(this.params{idx_params(2)}); + grid on; + + end + end @@ -1540,6 +1576,9 @@ function add_res(this,res) end end + + + end diff --git a/Core/Algos/@BreachProblem/solve_snobfit.m b/Core/Algos/@BreachProblem/solve_snobfit.m index 6c6c48f6..7355d0f4 100644 --- a/Core/Algos/@BreachProblem/solve_snobfit.m +++ b/Core/Algos/@BreachProblem/solve_snobfit.m @@ -89,7 +89,7 @@ clear x clear f - if isfield(this.BrSys.Sys, 'use_parallel') && this.BrSys.Sys.use_parallel + if isfield(this.BrSys, 'Sys') && isfield(this.BrSys.Sys, 'use_parallel') && this.BrSys.Sys.use_parallel % Parallel computation this.use_parallel = 1; x = request(:, 1:n); diff --git a/Core/BreachRequirement.m b/Core/BreachRequirement.m index 6248e5ed..9f5b42a6 100644 --- a/Core/BreachRequirement.m +++ b/Core/BreachRequirement.m @@ -41,18 +41,22 @@ this.AddRandReq(); end - elseif ischar(req_monitors)&&exist(req_monitors, 'file') - phis = STL_ReadFile(req_monitors); + elseif ischar(req_monitors)&&~isempty(regexp(req_monitors,'\.stl$','once')) + % req_monitors looks like .stl file + if exist(req_monitors,'file')==2 + phis = STL_ReadFile(req_monitors); - if nargin==1 - reqs= phis; + if nargin==1 + reqs= phis; + else + reqs = postprocess_signal_gens; + postprocess_signal_gens = {}; + end + this.AddReq(reqs); else - reqs = postprocess_signal_gens; - postprocess_signal_gens = {}; + error('BreachRequirement:STLFileNotFound','STL file not found: %s', req_monitors); end - this.AddReq(reqs); - - else + else this.AddReq(req_monitors); end else @@ -153,6 +157,20 @@ function ResetSigMap(this) end %% Evaluation + function Set_t0(this, t0) + % set initial time for requirements evaluation + for i_req = 1:numel(this.req_monitors) + r = this.req_monitors{i_req}; + r.t0 = t0; + end + + for i_req = 1:numel(this.precond_monitors) + r = this.req_monitors{i_req}; + r.t0 = t0; + end + end + + function ResetEval(this) this.BrSet = []; this.SetParam('data_trace_idx_', 0); @@ -168,7 +186,8 @@ function ResetEval(this) this.traces_vals = []; this.val = []; end - + + function [val_precond, traj_req] = evalTracePrecond(this,traj_req) % evalTracePrecond eval satisfaction of requirements for one trace. @@ -1150,11 +1169,17 @@ function Concat(this,other,fast) %% Display function varargout = disp(this) + reqs = ''; + for ifo = 1:numel(this.req_monitors) + reqs = [reqs this.req_monitors{ifo}.name ', ' ]; + end + reqs = reqs(1:end-2); + signals_in_st = cell2mat(cellfun(@(c) (['''' c ''', ']), this.signals_in, 'UniformOutput', false)); - signals_in_st = ['{' signals_in_st(1:end-2) '}']; + signals_in_st = signals_in_st(1:end-2); summary = this.GetStatement(); - st = sprintf('BreachRequirement object for signal(s): %s. %s\n', signals_in_st, summary.statement); + st = sprintf('BreachRequirement object with requirement(s) {%s} involving signal(s) {%s}. %s\n', reqs, signals_in_st, summary.statement); if nargout == 0 varargout = {}; diff --git a/Core/BreachSet.m b/Core/BreachSet.m index 69dd6394..2320f755 100644 --- a/Core/BreachSet.m +++ b/Core/BreachSet.m @@ -446,24 +446,33 @@ function SetParamGen(this, pg) end function SetParamGenItem(this, pg) - this.ParamGens{end+1} = pg; + % set a new param_gen. If new parameter is introduced, sets them to pg.p0 - % create/update domain of input parameters - this.SetParam(pg.params, pg.p0, true); - if ~isempty(pg.domain) - this.SetDomain(pg.params, pg.domain); + all_pg_params = [pg.params pg.params_out]; + all_pg_p0 = [pg.p0; nan(numel(pg.params_out),1)]; + + % We need to split between existing parameters + exist_params = this.GetParamList(); + + % checks for new parameters + [new_params, idx_new] = setdiff(all_pg_params, exist_params); + new_p0 = all_pg_p0(idx_new); + + % adds param_gen, and execute it (!) + this.ParamGens{end+1} = pg; + if ~isempty(new_params) + this.SetParam(new_params,new_p0, true); % Note: this is what creates the new parameters else - domain = repmat(BreachDomain, 1, numel(pg.params)); - this.SetDomain(pg.params, domain); + this.ApplyParamGens(pg.params); end - - % this.SetParam(pg.params_out, nan, true); % why ? - params_nan = setdiff(pg.params_out, pg.params); - if ~isempty(params_nan) - this.SetParam(params_nan, nan, true); + % if domain is specified we should set it + if ~isempty(pg.domain) + for ip =1:numel(pg.params_in) + this.SetDomain(pg.params{ip}, pg.domain{ip}); + end end - + % update domain of output parameters if ~isempty(pg.domain_out) for ip =1:numel(pg.params_out) @@ -471,7 +480,6 @@ function SetParamGenItem(this, pg) end end - this.ApplyParamGens(); end function ApplyParamGens(this, params) @@ -487,14 +495,28 @@ function ApplyParamGens(this, params) ip = params; params = this.P.ParamList{ip}; end + + % loop over list of param_gen and apply them for ig = 1:numel(this.ParamGens) pg = this.ParamGens{ig}; params_in= pg.params; - if ~isempty(intersect(params, params_in)) - p_in = this.GetParam(params_in); - p_out = pg.computeParams(p_in); - ip_out = FindParam(this.P, pg.params_out); - this.P.pts(ip_out,:) = p_out; + params_out = pg.params_out; + if ~isempty(intersect(params, [params_in params_out])) % if empty, this param_gen is not concerned + if isempty(params_out)&&isempty(params_in) + pg.computeParams(); % pure callback + elseif isempty(params_out)&&~isempty(params_in) + p_in = this.GetParam(params_in); + pg.computeParams(p_in) + elseif ~isempty(params_out)&&isempty(params_in) + p_out = pg.computeParams(); + ip_out = FindParam(this.P, pg.params_out); + this.P.pts(ip_out,:) = p_out; + else + p_in = this.GetParam(params_in); + p_out = pg.computeParams(p_in); + ip_out = FindParam(this.P, pg.params_out); + this.P.pts(ip_out,:) = p_out; + end end end if ~isempty(ig) @@ -1087,12 +1109,6 @@ function SaveSignals(this, signals, folder, name,i_trajs) SplotTraj(this.P, varargin{:}); end - function h= PlotSurf(this) - - - end - - %% Sampling function SampleDomain(this, params, num_samples, method, opt_multi, max_num_samples) % BreachSet.SampleDomain generic sampling function @@ -1385,7 +1401,7 @@ function SavedTrajectorySample(this, paramValues) end function PlotParams(this, varargin) - % Plot parameters + % Plot parameters legacy version gca; %P = DiscrimPropValues(this.P); params = SplotPts(this.P, varargin{:}); @@ -2923,6 +2939,8 @@ function plotydomain(dom, x0) end + + %% Plotting coverage function h = plot_cover_stats(this) % Plots coverage results in all projections as percentage bars if ~isempty(this.CoverRes) @@ -3373,7 +3391,7 @@ function plotydomain(dom, x0) end - + %% Requirements - sort of deprecated per BreachRequirement class function SortbyRob(this) sat_values = this.GetSatValues(); diff --git a/Core/BreachSystem.m b/Core/BreachSystem.m index 96b54a7c..fdc8861e 100644 --- a/Core/BreachSystem.m +++ b/Core/BreachSystem.m @@ -7,9 +7,6 @@ % class is derived from BreachSet. Type help BreachSet to view % properties and methods of the parent class. % - % BreachSystem Properties - % Specs - a set of Signal Temporal Logic (STL) formulas. - % % % BreachSystem methods % Sim - Simulate the system for some time using every parameter vectors. @@ -27,9 +24,10 @@ Sys % Legacy Breach system structure Specs % A set (map) of STL formulas ParamSrc = containers.Map() - use_parallel = 0 % the flag to indicate the usage of parallel computing - ParallelTempRoot = '' % the default temporary folder for parallel computing - InitFn = '' % Initialization function + use_parallel = 0 % the flag to indicate the usage of parallel computing + ParallelTempRoot = '' % the default temporary folder for parallel computing + parallel_batch_size = 80 % when running parSim, will run by patches of this size + InitFn = '' % Initialization function UseDiskCaching=false % set by SetupDiskCaching DiskCachingRoot end @@ -123,8 +121,8 @@ function SetupParallel(this, NumWorkers) end end - % clear up the ModelsData/ParallelTemp folder function StopParallel(this) + % clear up the ModelsData/ParallelTemp folder if license('test','Distrib_Computing_Toolbox') cwd = pwd; cd(this.ParallelTempRoot) @@ -161,41 +159,84 @@ function StopParallel(this) end end - function Bout = parSim(this, varargin) - % ALPHA tentative simpler parallel implementation. - - if isempty(gcp('nocreate')) - gcp; - end - if ~isempty(this.InitFn) - pctRunOnAll(this.InitFn); - end - - num_sim = this.GetNbParamVectors(); - num_task = num_sim; - if num_sim == 1 - this.Sim(varargin{:}) - else - % create tasks systems + function Bout = parSim(this, varargin) + % Simpler parallel implementation. + if license('test','Distrib_Computing_Toolbox') + + batch_size = this.parallel_batch_size; + if isempty(gcp('nocreate')) + gcp; + end + if ~isempty(this.InitFn) + pctRunOnAll(this.InitFn); + end + + num_sim_tot = this.GetNbParamVectors(); + + if num_sim_tot == 1 + this.Sim(varargin{:}) + else + h = waitbar(0,'Please wait...'); + num_sim = num_sim_tot; + num_done =0; + fprintf('\n'); + while num_sim>0 + num_task = min(num_sim, this.parallel_batch_size); + num_sim = num_sim-num_task; + + % create tasks systems + Btask = this.ExtractSubset(num_done+1); + for i = 2:num_task + Btask(i) = this.ExtractSubset(num_done+i); + end + + clear Bres task_queue + + for i = 1:num_task + task_queue(i) = parfeval(@(ii)(task_sim(Btask, ii, varargin{:})), 1, i); + end + + for i = 1:num_task + [completedIdx, value] = fetchNext(task_queue); + Bres{completedIdx} = value.copy(); + num_done = num_done+1; + fprintf('\b|\n'); + waitbar(num_done/num_sim_tot,h) + set(h, 'Name', sprintf('Running simulations %g/%g', num_done, num_sim_tot)); + drawnow + end + + %parfor i = 1:num_task + % Btask(i).Sim(varargin{:}); + % Bres{i} = Btask(i).copy(); % need to actually copy to get trace data + % fprintf('\b|\n'); + % end - for i = 1:num_sim - Btask(i) = this.ExtractSubset(i); + + for i = 1:num_task + + if (i==1)&&num_done==num_task + Bout = Bres{i}.copy(); + else + Bout.Concat(Bres{i},1) + end + end + %num_done = num_done+num_task; + fprintf('\b %g%%\n\n', floor(100*num_done/num_sim_tot)); + end + this.P = Bout.P; + %close(h) + end + else + warning('BreachSystem:parSim:ToolboxNotFound','Parallel toolbox not found, falling back to serial.') + Bout = this.Sim(varargin{:}); + end - - fprintf(2,[repmat('|',1,num_task) ' 100%%\n\n']); - parfor i = 1:num_task - Btask(i).Sim(varargin{:}); - Bres{i} = Btask(i).copy(); % need to actually copy to get trace data - fprintf('\b|\n'); - end - fprintf('\n'); - Bout = Bres{1}.copy(); - for i = 2:num_task - Bout.Concat(Bres{i},1) - end - this.P = Bout.P; - end - + function Bres_ii = task_sim(Btask, ii, varargin) + Btask(ii).Sim(varargin{:}); + Bres_ii = Btask(ii).copy(); % need to actually copy to get trace data + end + close(h) end @@ -251,7 +292,7 @@ function Sim(this,tspan) this.CheckinDomainParam(); if nargin==1 if this.hasTraj() - tspan = [0 this.P.traj{1}.time(end)]; + tspan = [0 this.P.traj{1}.time(1,end)]; else tspan = this.Sys.tspan; end diff --git a/Core/Gui/BreachGuiClass.m b/Core/Gui/BreachGuiClass.m index d4faa04a..6326e75b 100644 --- a/Core/Gui/BreachGuiClass.m +++ b/Core/Gui/BreachGuiClass.m @@ -1023,10 +1023,6 @@ function set_h(this,id,h) methods - - - - %% A template for a button. Replace truc with some label. function this = button_template(this, mode,name,string,callback,w,h) % Names diff --git a/Core/Gui/BreachProblemGui.m b/Core/Gui/BreachProblemGui.m index 7d29e0e0..ac671629 100644 --- a/Core/Gui/BreachProblemGui.m +++ b/Core/Gui/BreachProblemGui.m @@ -10,8 +10,9 @@ methods function this = BreachProblemGui(pb) - set(this.hdle, 'Name', 'BreachProblemGUI'), - + set(this.hdle, 'Name', 'BreachProblem GUI'), + + %% Linking problem object this.pb=pb; this.pb.callback_obj = @(o,e)(this.zcallback('pb',o,e)); @@ -25,44 +26,52 @@ this.Bsearch = B; - %% Creates all elements % objective ax this.create_axes('ax_main',2,8); this.create_panel('panel_plots', 'Objective', {{'ax_main'}}); - + % param table - id = 'table_params'; - cb =@(o,e)(this.table_params('callback',o,e)); - this.create_table(id, {},cb, 2, 4); - this.create_panel('panel_params', 'Search Domain', {{'table_params'}}); - this.table_params('init'); + this.button_reset_domain('create'); + this.button_apply_domain('create'); + this.table_params('create'); + this.checkbox_toggle_edit('create'); + this.create_panel('panel_params', 'Search Domain', ... + {{'checkbox_toggle_edit','button_reset_domain','button_apply_domain'}; ... + {'table_params'}}); % buttons - this.create_button('button_stop','Stop'); - this.create_button('button_resume','Start/Resume'); - this.create_panel('panel_buttons', 'Controls', {{'button_resume', 'button_stop'}}); - + this.button_stop('create'); + this.button_resume('create'); + + this.create_text('text_obj_eval', 'Max number of evaluations',.5,1) + this.edit_max_obj_eval('create'); + this.create_group('group_obj_eval', {{'text_obj_eval', 'edit_max_obj_eval'}}); + this.create_panel('panel_buttons', 'Controls', {{'group_obj_eval'}; ... + {'button_resume', 'button_stop'}}); + + % Layout layout = {{'panel_plots'}; {'panel_params'}; {'panel_buttons'}}; this.set_layout(layout); this.enable_resizable(); - + this.zcallback('pb'); end function zcallback(this,id,o,e) % callback function, called by the problem at each freq_update switch id - case 'button_stop' - this.pause_requested = 1; - case 'button_resume' - this.pause_requested= 0; - this.pb.is_paused = 0; - this.pb.solve(); case 'pb' + % update number of obj evaluations + panel_plots_title = ' Objective '; + obj_eval = num2str(size(this.pb.obj_log,2)); + max_eval = num2str(this.pb.max_obj_eval); + panel_plots_title = [panel_plots_title obj_eval ' / ' max_eval]; + this.set_by_id('panel_plots','Title', panel_plots_title); + ax=this.uimap('ax_main').hdle; axes(ax); enableDefaultInteractivity(ax); @@ -76,25 +85,149 @@ function zcallback(this,id,o,e) end - %% Domain table - function table_params(this, mode,o, e) + %% Domain panel + function button_reset_domain(this, mode,o, e) + w= .7; + h= 1; + cb = @(o,e)(this.button_reset_domain('callback', o, e)); switch mode - case 'init' - e = this.uimap('table_params'); - htable = e.hdle; - e.hdle = fill_uitable_params(htable,this.Bsearch); - set(e.hdle,'ColumnEditable', false); + case 'create' + e = this.create_button('button_reset_domain','Reset Search Domain ', cb, w,h); case 'callback' - % Todo + this.table_params('reset'); + end + end + + function button_apply_domain(this, mode,o, e) + w= .7; + h= 1; + cb = @(o,e)(this.button_apply_domain('callback', o, e)); + switch mode + case 'create' + e = this.create_button('button_apply_domain','Apply Changes', cb, w,h); + case 'callback' + this.table_params('apply'); end end + function checkbox_toggle_edit(this, mode,o, e) + w= .6; + h= 1; + cb = @(o,e)(this.checkbox_toggle_edit('callback', o, e)); + switch mode + case 'create' + e = this.create_checkbox('checkbox_toggle_edit','Edit Search Domain ', cb, w,h); + cb([],[]); + case 'callback' + v = this.get_by_id('checkbox_toggle_edit','Value'); + if v + this.set_by_id('button_apply_domain', 'enable', 'on'); + this.set_by_id('button_reset_domain', 'enable', 'on'); + this.set_by_id('table_params','ColumnEditable', true); + else + this.set_by_id('button_apply_domain', 'enable', 'off'); + this.set_by_id('button_reset_domain', 'enable', 'off'); + this.set_by_id('table_params','ColumnEditable', false); + end + end + end + + function table_params(this, mode,o, e) + id = 'table_params'; + w = 2; + h = 4; + switch mode + case 'create' + cb =@(o,e)(this.table_params('callback',o,e)); + elem_tble = this.create_table(id, {},cb, w, h); + htable = elem_tble.hdle; + elem_tble.hdle = fill_uitable_params(htable,this.Bsearch); + this.data_gui.(id).prev_data = get(elem_tble.hdle,'data'); + case 'callback' + % sanity test of input + idx= e.Indices; + data = get(o,'data'); + try + read_uitable_params(h_uitable); + catch ME + warning('BreachProblemGUI:InvalidEntry','Invalid data: %s', data{idx(1),idx(2)}); + set(o, 'data',this.data_gui.(id).prev_data) + end + case 'reset' + elem_tble = this.uimap('table_params'); + htable = elem_tble.hdle; + elem_tble.hdle = fill_uitable_params(htable,this.Bsearch); + case 'apply' + elem_tble = this.uimap('table_params'); + htable = elem_tble.hdle; + [params, p0, domains] = read_uitable_params(htable); + this.pb.BrSet.SetParam(params, p0); + this.pb.BrSet.SetDomain(params, domains); + this.pb.ResetObjective(); + end + + end + + %% Panel Control + function button_resume(this, mode,o, e) + w= 1; + h= 1; + cb = @(o,e)(this.button_resume('callback', o, e)); + switch mode + case 'create' + e = this.create_button('button_resume','Start/Resume', cb, w,h); + case 'callback' + this.pause_requested= 0; + this.pb.is_paused = 0; + this.pb.solve(); + end + end + + function button_stop(this, mode,o, e) + w= 1; + h= 1; + cb = @(o,e)(this.button_stop('callback', o, e)); + switch mode + case 'create' + e = this.create_button('button_stop','Stop', cb, w,h); + case 'callback' + this.pause_requested = 1; + end + end + + function edit_max_obj_eval(this, mode,o, e) + id = 'edit_max_obj_eval'; + w= .5; + h= 1; + cb = @(o,e)(this.edit_max_obj_eval('callback', o, e)); + string = ''; + switch mode + case 'create' + this.create_edit('edit_max_obj_eval',string, cb, w,h); + this.edit_max_obj_eval('update'); + case 'callback' + max_eval = str2double(this.get_by_id(id, 'String')); + this.pb.max_obj_eval = max_eval; + case 'update' + max_eval = num2str(this.pb.max_obj_eval); + this.set_by_id(id,'String',max_eval); + end + end + + %% Plotting % TODO more options, axes, etc % function reset_obj_plot(this) % % end - + function reset_top_fig(this) + % we enable figure toolbar since we have axes + this.hdle = figure('Name',this.title, ... + 'Toolbar', 'figure',.... + 'Menubar', 'none',... + 'NumberTitle','off',... + 'SizeChangedFcn', @(o,e)(this.resize_callback(o,e))); + end end diff --git a/Core/OutputGen/stl_monitor.m b/Core/OutputGen/stl_monitor.m index 13c91281..c05e20fe 100644 --- a/Core/OutputGen/stl_monitor.m +++ b/Core/OutputGen/stl_monitor.m @@ -92,7 +92,7 @@ function set_out_signal_names(this, sigs) this.init_tXp(time,X,p); % compute robustnes of top formula at time 0 - [time, Xout] = this.get_standard_rob(this.formula, 0); + [time, Xout] = this.get_standard_rob(this.formula, this.t0); end function [v, t, Xout] = eval(this, t, X,p) diff --git a/Core/ParamGen/equal_param_gen.m b/Core/ParamGen/equal_param_gen.m index 804cb475..e0131d5f 100644 --- a/Core/ParamGen/equal_param_gen.m +++ b/Core/ParamGen/equal_param_gen.m @@ -1,5 +1,5 @@ classdef equal_param_gen < param_gen - % equal_param_gen enforces one param_out to be always equal to param_in + % equal_param_gen enforces a set of param_out to be always equal to one param_in properties n_out @@ -8,6 +8,8 @@ methods function this = equal_param_gen(param_in, param_out, p0) this.params = {param_in}; + + if ~iscell(param_out) param_out={param_out}; end @@ -15,7 +17,7 @@ this.n_out= numel(this.params_out); if nargin<3 - p0= 0; + p0=0; end this.p0 =p0; end diff --git a/Core/ParamGen/expr_param_gen.m b/Core/ParamGen/expr_param_gen.m index 4ea0332e..9d67a86e 100644 --- a/Core/ParamGen/expr_param_gen.m +++ b/Core/ParamGen/expr_param_gen.m @@ -11,7 +11,7 @@ this.params_out = {param_out}; if nargin<3 - p0 = 0; + p0 = zeros(numel(this.params),1); end this.p0 = p0; diff --git a/Ext/Toolboxes/wordgen/BreachTASignalGen.m b/Core/SignalGen/BreachTASignalGen.m similarity index 100% rename from Ext/Toolboxes/wordgen/BreachTASignalGen.m rename to Core/SignalGen/BreachTASignalGen.m diff --git a/Ext/Toolboxes/wordgen/TA_signal_gen.m b/Core/SignalGen/TA_signal_gen.m similarity index 95% rename from Ext/Toolboxes/wordgen/TA_signal_gen.m rename to Core/SignalGen/TA_signal_gen.m index 0cfd1274..5eb45b08 100644 --- a/Ext/Toolboxes/wordgen/TA_signal_gen.m +++ b/Core/SignalGen/TA_signal_gen.m @@ -3,7 +3,7 @@ TA_file num_evts labels - wordgen_exe = './wordgen' + wordgen_exe = 'wordgen' poly = 5 template_in template_out @@ -31,6 +31,11 @@ this.params_cp = this.params; this.TA_file = TA_file; + [this.wordgen_exe found] = find_wordgen_exe(); + + if ~found + warning('wordgen executable not found.'); + end this.labels=labels; @@ -59,9 +64,9 @@ end - function X = computeSignals(this,p, time) % compute the signals + function [X, time] = computeSignals(this,p, time) % compute the signals p_cp = computeParams(this, p); - X = computeSignals@var_cp_signal_gen(this, p_cp, time); + X = computeSignals@var_cp_signal_gen(this, p_cp, time); end function p_cp = computeParams(this, p_evt) diff --git a/Ext/Toolboxes/wordgen/TA_signal_gen2.m b/Core/SignalGen/TA_signal_gen2.m similarity index 96% rename from Ext/Toolboxes/wordgen/TA_signal_gen2.m rename to Core/SignalGen/TA_signal_gen2.m index aa911648..151cc711 100644 --- a/Ext/Toolboxes/wordgen/TA_signal_gen2.m +++ b/Core/SignalGen/TA_signal_gen2.m @@ -3,7 +3,7 @@ TA_file num_evts labels - wordgen_exe = './wordgen' + wordgen_exe = 'wordgen' poly = 5 expected_duration = 0 template_in @@ -35,16 +35,13 @@ this.params_cp = this.params; this.TA_file = TA_file; - if ispc - this.wordgen_exe = which('wordgen.exe'); - else - this.wordgen_exe = which('wordgen'); - end - - if isempty(this.wordgen_exe) + [this.wordgen_exe found] = find_wordgen_exe(); + + if ~found warning('wordgen executable not found.'); end + this.labels=labels; this.num_evts = num_evt; @@ -91,7 +88,7 @@ cmd_template = [strrep(exe,'\','\\') ' ' strrep(in_file,'\','\\') ' --template "%s"' ... - '" --poly ' num2str(this.poly)]; + ' --poly ' num2str(this.poly)]; if this.expected_duration > 0 cmd_template = [cmd_template ... diff --git a/Core/SignalGen/signal_gen.m b/Core/SignalGen/signal_gen.m index 1638bdb5..3bf13feb 100644 --- a/Core/SignalGen/signal_gen.m +++ b/Core/SignalGen/signal_gen.m @@ -22,6 +22,7 @@ params_out_domain domains = containers.Map() % maps all of the above to their respective domains, supposedly (TODO) p0 % default values + t0=0 % signal start time end methods diff --git a/Core/m_src/create_breachsignalgen.m b/Core/m_src/create_breachsignalgen.m index 9ad862e0..8febb608 100644 --- a/Core/m_src/create_breachsignalgen.m +++ b/Core/m_src/create_breachsignalgen.m @@ -1,5 +1,5 @@ function B = create_breachsignalgen(dim, varargin) -% create_breachset(dim, varargin) +% create_breachsignalgen(dim, varargin) % % returns a BreachSet object of various dimensions with default names for % parameters ('p1', 'p2', etc), with domains [0,1] diff --git a/Core/m_src/fill_uitable_params.m b/Core/m_src/fill_uitable_params.m index d0cc2080..fda5852a 100644 --- a/Core/m_src/fill_uitable_params.m +++ b/Core/m_src/fill_uitable_params.m @@ -61,9 +61,9 @@ set(h_uitable, 'data', data); max_sz = max(sz); % longest param names in table if ismac - SZ = {max_sz*7 80 80 80 80} ; + SZ = {max(100, max_sz*7) 80 80 80 80} ; else - SZ = {max_sz*8 100 100 100 100} ; + SZ = {max(120, max_sz*8) 100 100 100 100} ; end set(h_uitable, 'ColumnWidth', SZ, 'Unit', 'pixel'); diff --git a/Core/m_src/find_wordgen_exe.m b/Core/m_src/find_wordgen_exe.m new file mode 100644 index 00000000..2d50c5a2 --- /dev/null +++ b/Core/m_src/find_wordgen_exe.m @@ -0,0 +1,15 @@ +function [wordgen_exe, found] = find_wordgen_exe() + +Ext_path = BreachGetExtPath(); +wg_path = [Ext_path filesep 'Toolboxes' filesep 'wordgen']; + +if ispc + wordgen_exe = 'wordgen.exe'; +else + wordgen_exe = 'wordgen'; +end + +wordgen_exe = [wg_path filesep wordgen_exe]; +found = (exist(wordgen_exe, 'file')==2); + +end \ No newline at end of file diff --git a/Core/m_src/rtr.mexw64 b/Core/m_src/rtr.mexw64 index 01152bf0..01045b7e 100755 Binary files a/Core/m_src/rtr.mexw64 and b/Core/m_src/rtr.mexw64 differ diff --git a/Doc/index.html b/Doc/index.html index 218452f4..66e07c0e 100644 --- a/Doc/index.html +++ b/Doc/index.html @@ -6,7 +6,7 @@ List of scripts

List of scripts

Generated on 25-Jan-2022 18:12:29 with Breach Version 1.9.1

+

List of scripts

Generated on 13-Feb-2024 12:44:36 with Breach Version 1.11.3

-