⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 piha.m

📁 一个matlab的将军模型
💻 M
📖 第 1 页 / 共 4 页
字号:
function piha(sys)

% Polyhedral invariant hybrid automaton compiler 
%
% This compiler uses a modified method to create a PIHA from the switched
% continuous system.  Instead of dividing the entire state space region with
% every hyperplane associated with all of the PTHB's, this method creates a
% partition of the analysis region for each discrete location.  The analysis 
% region for each location is then partitioned only with the pthb's that
% are relevant for that location (i.e. only the pthb's which define the guards).
%Also, clock information and reset information are collected and attached to the 
%transition information.  
%
%A location is created for each finite state in the
%Stateflow machine(s).  An interior region is defined for each location.  This interior
%region is a collection of pointers to the structure 'cells' which is a collection
%of convex regions (i.e. so the interior regions are made up of a collection of smaller
%convex regions).  
%
%Each location also contains information about each of its 'exiting'
%transitions.  Information about transitions are contained within each 'transition'.
%This information includes:
%
%-'id'	     					the number of the transition (assigned by Stateflow)
%-'expression'					the expression attached to the transition
%-'clock'							the clock number (if there is one)
%-'source'						the source state (identified by the value of 'q')
%-'destination'					the source state (identified by the value of 'q')
%-'destination_name'			the label given to the destination
%-'reset_flag'					set if there is a reset associated with this transition
%-'guard'							pointers to elements in 'cells' that define the guard regions
%-'guard_cell_event_flags'	a matrix where the i'th row is a vector of flags identifying
%									which boundary hyperplane of the i'th guard cell is an event
%									hyperplane
%-'guard_compl'					cells which define the complement of the cells in 'guard'
%
%
%
% Syntax:
%   "HA = piha(sys)"
%
% Description:
%   "piha(sys)" returns a PIHA object.  The returned PIHA object is
%   equivalent to the Simulink CheckMate model "sys" within the analysis
%   region.
%

% "only_condition_inputs_flag" added by JimK (11/2002).  The purpose of the flag
% is to notify "create_guard" if there are only condition inputs into the stateflow
% block.  If this is the case, all edges should be flagged as event edges.

%
% Last change: 11/18/2002 JPK


global GLOBAL_PIHA SSTREE CELLS LOCATIONS

CELLS={};

if ~isstr(sys)
  error(['Input argument must be a string.'])
  return
end

if strcmp(sys,'help')
  fid = fopen('@piha/piha_structure.txt');
  while 1
    line = fgetl(fid);
    if ~isstr(line), break, end
    fprintf(1,'%s\n',line)
  end
  fclose(fid);
  return
end

% Check the model syntax before performing conversion
if ~check_model_syntax(sys)
  fprintf(1,'\007Syntax error, model conversion aborted.\n')
  return
end

% Find Simulink handles for switched continuous system blocks (SCSB),
% finite state machine blocks (FSMB), and polyhedral threshold blocks
% (PTHB) in the CheckMate model.
scsbHandle = find_masked_blocks(sys,'SwitchedContinuousSystem');
fsmbHandle = find_masked_blocks(sys,'Stateflow');
pthbHandle = find_masked_blocks(sys,'PolyhedralThreshold');
clockHandle = find_masked_blocks(sys,'VariableZeroOrderHold');

clockList=[];
%Create a list of all clocks and their associated parameters
for c=1:length(clockHandle)
   clockList{c}.name  = get_param(clockHandle(c),'name');
   clockList{c}.period =evalin('base',get_param(clockHandle(c),'period'));
   clockList{c}.jitter =evalin('base',get_param(clockHandle(c),'jitter'));
   clockList{c}.phase =evalin('base',get_param(clockHandle(c),'theta'));
end

% **********************************
% (1) Construct list of hyperplanes.
% **********************************

% Get threshold hyperplanes from the PTHBs in the simulink model.
disp('Compiling threshold hyperplanes.')
NBDHP = {};
for k = 1:length(pthbHandle)
    [Ck,dk] = augment_poly_constraints(scsbHandle,pthbHandle(k));
    pthb{k}.c=Ck;
    pthb{k}.d=dk;
    pthb{k}.hps=[];
    for l = 1:length(dk)  
        new = length(NBDHP)+1;
        NBDHP{new}.pthb = k;
        NBDHP{new}.index = l;
        NBDHP{new}.c = Ck(l,:);
        NBDHP{new}.d = dk(l,:);
    end%for
end%for

%Create hyperplane list
AR = get_analysis_region(scsbHandle);
[pthb,NAR]=create_hyperplanes(NBDHP,AR,pthb);


% **************************************************************************
% (3) Build data base for Stateflow blocks that will be used for conversion.
% **************************************************************************

machine_id = get_machine_id(sys);
if isempty(machine_id)
  fprintf(1,['\007Error: Cannot find machine id for ''' sys '''!!!\n'])
  return
end

sfdata = {};

for k = 1:length(fsmbHandle)

    block_name = get_param(fsmbHandle(k),'Name');
    chart_id = find_chart_id(machine_id,block_name);
  
    if isempty(chart_id)
        fprintf(1,['\007Error: Cannot find chart id for "' block_name '"!!!\n'])
        return
    else
    
        data_id = sf('find',sf('DataOf',chart_id),'.scope','INPUT_DATA');
        input_data = {};
        clock=[];
        in_num=0;

        for l = 1:length(data_id)
      
            [expression,clock_handle]=sf_input_expression(fsmbHandle(k),'data',l);
            if ~isempty(clock_handle)
                error(['Clocks must be event inputs.'])
            else
                in_num=in_num+1;
                input_data{in_num}.Name = sf('get',data_id(l),'.name');
                if input_data{in_num}.Name(1)==' '|input_data{in_num}.Name(length(input_data{in_num}.Name))==' '
                            error('The names of Stateflow input data variables cannot have leading or trailing spaces.')
                end
                        
                input_data{in_num}.Expression = expression;
      	    end%if
        
        end%for
    
        event_id = sf('find',sf('EventsOf',chart_id),'.scope','INPUT_EVENT');
        input_event = {}; 

        for l = 1:length(event_id)

            event_name = sf('get',event_id(l),'.name');
            if event_name(1)==' '|event_name(length(event_name))==' '
                            error('The names of Stateflow input events cannot have leading or trailing spaces.')
            end
            if ~strcmp(event_name,'start')

                [expression,clock_handle]=sf_input_expression(fsmbHandle(k),'event',l);

                if ~isempty(clock_handle)
                    clock_num=length(clock)+1;
                    clock{clock_num}.Name=sf('get',event_id(l),'.name');
                    clock{clock_num}.ClockBlock=get_param(clock_handle,'name');
                    clock{clock_num}.ClockHandle=clock_handle;
                else

       
               	    % ignore the start event, which is used only for simulation purpose
        	        new = length(input_event)+1;
        	        input_event{new}.Name = event_name;
    
                    if ~isempty(sf('find',event_id(l),'.trigger','RISING_EDGE_EVENT'))
                	    input_event{new}.Trigger = 'RISING_EDGE_EVENT';   
        	         end

                    if ~isempty(sf('find',event_id(l),'.trigger','FALLING_EDGE_EVENT'))
    	                input_event{new}.Trigger = 'FALLING_EDGE_EVENT';   
    	            end

                    if ~isempty(sf('find',event_id(l),'.trigger','EITHER_EDGE_EVENT'))
                	    input_event{new}.Trigger = 'EITHER_EDGE_EVENT';   
                    end
  
                     if strcmp('RISING_EDGE_EVENT',input_event{new}.Trigger)
                        input_event{new}.Expression = ...
                     	 sf_input_expression(fsmbHandle(k),'event',l);
                    elseif strcmp('FALLING_EDGE_EVENT',input_event{new}.Trigger)
                         input_event{new}.Expression = ...
                 	    ['~(' sf_input_expression(fsmbHandle(k),'event',l) ')'];
                    else
                        error('This version only supports  rising and falling event edges!')
                    end%if
               
                end%if
            end%if
        end%for
    
        sfdata{k}.BlockName = block_name;
        sfdata{k}.SimulinkHandle = fsmbHandle(k);
        sfdata{k}.StateflowChartID = chart_id;
        sfdata{k}.InputData = input_data;
        sfdata{k}.InputEvent = input_event;
        sfdata{k}.Clock = clock;
           
    end%if
    
end%for

% **************************************************************
% (4) Find initial discrete states for all the Stateflow blocks.
% **************************************************************

% Get initial state id for each Stateflow block, assuming that there is 
% only one default transition per machine.
q0 = []; 
for k = 1:length(sfdata)
  chart_id = sfdata{k}.StateflowChartID;
  DTid = sf('DefaultTransitionsOf',chart_id);
  q0id = sf('get',DTid,'.dst.id');
  q0(k) = q0id;
end

%**************************************************************
%Create list of locations and all guards for each location
%**************************************************************
k=ones(1,length(sfdata));
%Find the total number of possible locations
no_loc=1;
for j=1:length(sfdata)
   machine{j}.states=sf('get',sfdata{j}.StateflowChartID,'.states');
   no_loc=no_loc*length(machine{j}.states);
end
locations=[];

% Reset operation. It maps the FSMB to SCSB
% Ansgar Fehnker 09/16/2002
 

% Compute which fsmb is connceted to which scsb
for k0 =1:length(fsmbHandle)
  fsmb2scsb{k0} = [];
end

for k1 = 1:length(scsbHandle)
  if strcmp(get_param(scsbHandle(k1),'use_reset'),'on')
    inputfsmb_Handle = trace_scsb_input(scsbHandle(k1),'reset');
    % The error checking in trace_scsb_input ensures that only one FSMB
    % is returned in inputfsmb_Handle.
    fsmbindex = find(inputfsmb_Handle == fsmbHandle);
    fsmb2scsb{fsmbindex} = [fsmb2scsb{fsmbindex} k1];
  end
end
    
%Find all possible locations by attempting all combinations of states
%and machines
for j=1:no_loc
   
   %Test each combination to see if it is a null state
   for i=1:length(sfdata)
      q(i)=machine{i}.states(k(i));
   end
   null_state=is_terminal_state(q);
   if null_state==0
      new=length(locations)+1;
      number_trans=0;
      for l=1:length(q)
         % "only_condition_inputs_flag" added by JimK (11/2002).  The purpose of the flag
         % is to notify "create_guard" if there are only condition inputs into the stateflow
         % block.  If this is the case, all edges should be flagged as event edges.
         if isempty(sfdata{l}.InputEvent)
            only_condition_inputs_flag = 1;
         else
            only_condition_inputs_flag = 0;
         end
      	transitions=sf('get',q(l),'.srcTransitions');
      	names=sf('get',transitions,'.labelString');
         for p=1:size(names,1)
            number_trans=number_trans+1;
            locations{new}.transitions{number_trans}.id=transitions(p);
            [event_expr,condition_expr,clock,reset_flag]=process_label_string(names(p,:),sfdata,l,clockHandle);
            [total_expression,event_expression,condition_expression]=find_cond_expr(sfdata,condition_expr,event_expr,l);            
            locations{new}.transitions{number_trans}.expression=total_expression;
            locations{new}.transitions{number_trans}.clock=clock;
                        locations{new}.transitions{number_trans}.idx=l;    % Zhi add this to record the index of transition in q
            locations{new}.transitions{number_trans}.source=sf('get',transitions(p),'.src.id');
            locations{new}.transitions{number_trans}.destination=sf('get',transitions(p),'.dst.id');
            locations{new}.transitions{number_trans}.destination_name=sf('get',sf('get',transitions(p),'.dst.id'),'.name');
            locations{new}.transitions{number_trans}.reset_flag=reset_flag;

            % Stores the scsb that defines the reset
            locations{new}.transitions{number_trans}.reset_scs_index=fsmb2scsb{l};

            %Find guard region.  Result will be pointers to cell locations which describe this guard
            [guard_cells,guard_cell_event_flags,guard_compl_cells]=create_guard(condition_expression,event_expression,pthbHandle,pthb,NAR,only_condition_inputs_flag);
            locations{new}.transitions{number_trans}.guard=guard_cells;
            locations{new}.transitions{number_trans}.guard_cell_event_flags=guard_cell_event_flags;
            locations{new}.transitions{number_trans}.guard_compl=guard_compl_cells;

         end %for
      end%for
      %Use guard complements from every transition from this location to compute
      %the 'invariant' for this location.  The idea is to intersect all of the
      %complements of the guards for this location.  This is done iteratively by
      %intersecting the first guard complement with the next, then taking the result 
      %and intersecting it with the 3rd and so on (i.e  ( A and B ) and C ....)
%       clean_loc=clean_transition(locations{new});
%        locations{new}.transitions=clean_loc.transitions;
           locations{new}.q=q;
      locations{new}.state=sf('get',q,'.name');
      locations{new}.interior_cells=[];
           invariant=intersect_complements(locations,new);
      locations{new}.interior_cells=invariant;
   end%if
   
      
   
   for n=1:length(k)
      if k(n)+1<=length(machine{n}.states)
            k(n)=k(n)+1;
            break;
      else
            k(n)=1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -