www.gusucode.com > mbcview 工具箱matlab源码程序 > mbcview/+cgcalsetup/TableData.m

    classdef TableData < cgcalsetup.ModelData
    %TableData data object for creating tables and tradeoffs from a model
    %
    % C = cgcalsetup.TableData(pNode,MakeTables);
    
    %  Copyright 2009-2013 The MathWorks, Inc. and Ford Global Technologies, Inc.
    
    properties (SetObservable,AbortSet)
        %TableInputs index to inputs for use as table inputs
        TableInputs
        %BreakPoints - breakpoints for table
        BreakPoints
        %pNorm - pointers to table normalizers
        pNorm = mbcpointer(1,2);
        %CreateTables - logical array indicating which tables to make
        CreateTables
        %MakeTables
        CreateTradeoff = false;
        %pItems - list of all possible items to create
        pItems
        %TableName - names of tables
        TableName
        %pTables array of pointers to tables
        pTables = xregpointer;
        %pFill - filling items for tables
        pFill
        %TableRange ranges for new tables
        TableRange
    end
    
    properties (SetObservable)
        %UseOpPoints use model operating points for normalizer values
        UseOpPoints
    end
    
    properties (Dependent)
        %TabInputList list of inputs available as table inputs. 
        % TabInputList is restricted to SwitchFactors if IsSwitchExpr is
        % true.
        TabInputList
        %pTableInputs list of inputs to table
        pTableInputs
    end
    
    methods
        
        function C = TableData(varargin)
            %TableData - constructor
            C@cgcalsetup.ModelData(varargin{:});
            C.Title = 'Tables and Tradeoff';
            C.Description = 'Select a model to base the new tables on.';
            C.ErrorMessage = 'You must have models with at least two inputs in the CAGE project before you can create tables from a model.';
        end
        
        function set.TableInputs(C,NewValue)
            %select which inputs to use as table inputs
            if length(NewValue)==2 && length(C.TableInputs)==2
                Changed = C.TableInputs~=NewValue;
                if sum(Changed)==1
                    OldValues = C.TableInputs;
                    if any(OldValues(~Changed) == NewValue(Changed))
                        % copy value changing to the other table input
                        NewValue(~Changed) = OldValues(Changed);
                        Changed(~Changed) = true;
                    end
                end
                C.TableInputs = NewValue;
                for i= find(Changed)
                    setDefaultBreakPoints(C,i)
                end
            else
                C.TableInputs = NewValue;
            end
        end
        
        function pTabInputs = get.TabInputList(C)
            if C.UseOpPoints
                pTabInputs = C.pSwitchInputs;
            else
                pTabInputs = [C.pInputs address(C.Model)];
            end
            
        end
        
        function set.UseOpPoints(C,NewValue)
        
        C.UseOpPoints = NewValue;
        setDefaultInputs(C);
        setDefaultBreakPoints(C,1)
        setDefaultBreakPoints(C,2)
        
        end

        
        
        function pTabInputs = get.pTableInputs(C)
        if C.UseOpPoints
            pTabInputs = C.pSwitchInputs(C.TableInputs);
        else
            pTabInputs = C.TabInputList(C.TableInputs);
        end
        
        end
        
        function   createItems(C)
            %createItems - create table items for model
            createItems@cgcalsetup.ModelData(C);
            if any(C.CreateTables)
                createTables(C);
            end
            
        end
        
        function defineItems(C)
            %defineItems - set up defaults based on selection of normalizer
            %inputs
            
            pOther = findAllAdditionalModels(C);
            pAll = [C.pInputs,address(C.Model),pOther];
            [~,ia] = setdiff(pAll,C.pTableInputs);
            
            C.pItems = pAll(sort(ia));
            Names = pveceval(C.pItems,@getname);
            Ranges = cell(length(C.pItems),1);
            for i=1:length(Names)
                Names{i} = sprintf('%s_Table',Names{i});
                if C.pItems(i).isinport
                    Ranges{i} = C.pItems(i).getrange;
                else
                    Ranges{i} = [-Inf Inf];
                end
            end
            C.TableName = Names;
            C.TableRange = Ranges;
            C.CreateTables = true(size(C.pItems));
            % don't make tables for extra models
            C.CreateTables(end-length(pOther)+1:end) = false;
        end
        
        function setDefaultBreakPoints(C,index,Size)
            %setDefaultBreakPoints set up default breakpoints for tables
            %
            % setDefaultBreakPoints(C,index,Size)
            
            if nargin<3
                if length(C.BreakPoints)>=index
                    Size = length(C.BreakPoints{index});
                else
                    Size = 10;
                end
            end
            
            if index>length(C.pTableInputs)
                setDefaultInputs(C)
            end
            
            pTableInput = C.pTableInputs(index);

            if C.UseOpPoints
                % switch models
                [OK,loc]=ismember(pTableInput,C.pSwitchInputs);
                if OK(1)
                    SwitchModel = getSwitchModel(C.Model);
                    OpPoints = getSwitchPoints(SwitchModel);
                    tol = getAbsoluteTolerance(get(SwitchModel,'model'));
                    C.BreakPoints{index} = curvefitlib.internal.uniqueWithinTol(OpPoints(:,loc(1)),tol(loc(1)));
                end
            else
                if pTableInput.isinport
                    % auto space models based on variable range
                    r  = pTableInput.getrange;
                    C.BreakPoints{index} = linspace(r(1),r(2),Size);
                else
                    % Model Output -> use [0,1] as default range
                    C.BreakPoints{index} = linspace(0,1,Size);
                end
            end
        end

        
        function changeBreakpointSize(C,index,Size)
        
        bp = C.BreakPoints{index};
        if length(bp)~=Size
            % use min and max from current values
            C.BreakPoints{index} = linspace(bp(1),bp(end),Size);
        else
            % no change in breakpoints
        end
        end
        
        function f = getModelNextPage(W) %#ok<MANU>
            %getModelNextPage - page to follow the model page in wizard
            %
            % f = getModelNextPage(W)
            %   The normalizer page follows the model page
            
           f = @cgcalsetup.NormalizerPage.createPage;
       end
        
    end
    
    methods (Access=protected)
        function initializeSwitchTables(C)
            %initializeSwitchTables initialize tables for switch models
            
            mdl = getSwitchModel(C.Model);
            
            [OK,loc]= ismember(C.pInputs,getinputs(mdl));
            InputVals = cell(1,length(C.pInputs));
            if ~all(OK)
                % use nominal values where input is not an input to the switch model 
                InputVals(~OK) = pveceval(C.pInputs(~OK),@getnomvalue);
            end
            % use initial values for all other inputs
            m =  get(mdl,'model');
            data = InitialValues(m);
            InputVals(OK) = num2cell( data(:,loc(OK)), 1);
            

            [OK,loc]=ismember(C.pInputs,C.pFill);
            Y = cell(1,length(C.pFill));
            Y(loc(OK))= InputVals(OK);
            for j= sum(OK)+1:length(C.pFill)
                % evaluate expressions
                Y{j} = cgsimfill.ExpressionChain.fastEvaluate(C.pFill(j).info,InputVals);
            end

            TableVals = pveceval(C.pTables,@(T) get(T,'values'));
            Mask = false(size(TableVals{1}));
            TableBreakPoints = pveceval(C.pNorm,@(T) get(T,'breakpoints'));

            
            [~,loc] = ismember(C.pTableInputs,C.pInputs);
            for i=1:size(data,1)
                % find grid point
                IndX = find(InputVals{loc(2)}(i) == TableBreakPoints{2});
                IndY = find(InputVals{loc(1)}(i) == TableBreakPoints{1});
                if ~isempty(IndX) && ~isempty(IndY)
                    % extrapolation mask
                    Mask(IndY,IndX) = true;
                    for j=1:length(C.pTables)
                        % update table value
                        TableVals{j}(IndY,IndX) = Y{j}(i);
                    end
                end
            end
            
            for j=1:length(C.pTables)
                % make note for history
                if C.pFill(j).isinport
                    Note = sprintf('Initial values for ''%s'' using point-by-point model ''%s''',C.pInputs(j).getname,getname(mdl));
                else
                    Note = sprintf('Initial values using point-by-point model ''%s''',getname(mdl));
                end
                % set values
                LT = set(C.pTables(j).info,'values',{TableVals{j},Note});
                % set mask and extrapolate
                [Rows,Cols]= find(Mask);
                LT= addToExtrapolationMask(LT,Rows,Cols);
                LT= extrapolate(LT);
                C.pTables(j).info = LT;
            end
        end
        
        function setModelNode(C)
            %setModelNode initializes TableData for a model
            
            setModelNode@cgcalsetup.ModelData(C);
            C.UseOpPoints = isSwitchModel(C) && length(C.pSwitchInputs)>=2;
            C.CreateTradeoff= true;
            defineItems(C)
        end
        
        function setDefaultInputs(C)
        if C.UseOpPoints
            [~,loc] = ismember(C.pSwitchInputs,C.TabInputList);
            loc = loc(1:2);
        else
            % use last two
            loc = length(C.pInputs)-1:length(C.pInputs);
        end
        C.TableInputs = loc;
        end

        
        function pList = getModelList(C)
            %getModelList models have to have at least 2 inputs
            
            pList = getModelList@cgcalsetup.ModelData(C);
            if ~isempty(pList)
                pInp=pveceval(pList,@getinports);
                pList = pList(cellfun(@length,pInp)>=2);
            end
        end
        
        function [pItems,pExpr] = getCreatedItems(C)
            %getCreatedItems list of created items and associated expressions
            %
            % [pItems,pExpr] = getCreatedItems(C)
            
            [pItems,pExpr] = getCreatedItems@cgcalsetup.ModelData(C);
            if ~any(isnull(C.pTables))
                pExpr = [pExpr, C.pFill];
            end
            if C.CreateTradeoff
                pExpr = [pExpr, address(C.Model)];
            end
        end
        
        function createTables(C)
            %createTables create tables for model
            
            pTableInputs = C.pTableInputs;
            OriginalNorms = C.pNorm;
            setupNormalizers(C,pTableInputs);
            
            % Make the tables for the variables
            createAllTables(C);
            
            if any(isnull(OriginalNorms))
                % record that normalizers were created 
                pAddItems = [C.pNorm(isnull(OriginalNorms)), C.pTables];
            else
                pAddItems = C.pTables;
            end
            hAddItems = infoarray(pAddItems);
            ndP = null(xregpointer, 1, length(pAddItems));
            for n = 1:length(ndP)
                % make nodes
                ndP(n)=cgnode(hAddItems{n},[],pAddItems(n),1);
            end
            CGP = C.Project;
            % Add the items to the project
            CGP.addnodestoproject(ndP);
            
            addCreatedItems(C,pAddItems);
            
            if C.UseOpPoints
                %initialize tables for point-by-point models
                initializeSwitchTables(C)
            end
            
            if C.CreateTradeoff
                createTradeoff(C,C.pTables,C.pFill)
            end

            if isMultiModal(C.Model)
                % set precision of Mode table to polynomial to restrict
                % table values to integers
                [~,pInp]=getSwitchModel(C.Model);
                [OK,loc]=ismember(pInp(end),C.pFill);
                if OK
                    C.pTables(loc).info= set(C.pTables(loc).info,'precision',cgprecpolyfix);
                end
            end
            
            if any(isnull(OriginalNorms))
                % add table inputs to fill list to match normalizers
                C.pFill = [pTableInputs(isnull(OriginalNorms)) C.pFill];
            end

        end
        
        function createTradeoff(C,pTables,pFill)
            %createTradeoff 
            %
            % createTradeoff(C,pTables,pFill)
            
            TO = cgtradeoffnode(sprintf('%s_Tradeoff',getname(C.Model)));
            CGP = C.Project;
            CGP.addnodestoproject(address(TO));
            
            TO = info(TO);
            for i=1:length(pTables)
                % add table to tradeoff
                TO = addTable(TO, pTables(i), false) ;
                if C.UseOpPoints
                    % use model to define valid operating points
                    TO = setFillExpression(TO, pTables(i), pFill(i),address(C.Model));
                else
                    % set fill expression for table
                    TO = setFillExpression(TO, pTables(i), pFill(i));
                end
            end
            % need to make sure that the project connections are updated to include
            % links tables and models
            CGP.UpdateConnections(address(TO));
            if C.UseOpPoints
                % initialize tradeoff in table mask
                TO = initTableInputsForValidCells(TO, C.pTables(end));
            end
            mask = C.pTables(end).getExtrapolationMask;
            if ~isempty(mask) && any(mask(:))
                TO = updateFromTables(TO,mask);
            end
            addCreatedItems(C, address(TO));
        end

    end
end


function setupNormalizers(C,pTableInputs)
%setupNormalizers setup or create normalizers for tables

if isempty(C.pNorm)
    C.pNorm = mbcpointer(1,2);
end
for i=1:length(C.pNorm)
    if isnull(C.pNorm(i))
        % create the normalizers for the tables
        C.pNorm(i) = iCreateNorm(C,pTableInputs(i),C.BreakPoints{i});
    else
        %use existing normalizers
        C.pNorm(i) = C.pNorm(i);
    end
end
end

function pNorm = iCreateNorm(C,pTableInput,Breakpoints)
%iCreateNorm main creation routine for normalizer
%
% pNorm = iCreateNorm(pTableInput,Breakpoints)

% Make the normalisers for the tables
inputname = pTableInput.getname;
if ~pTableInput.isinport
    % create variable called <modelname>_input
    [~,pTableInput] = add(info(C.Project.getdd), [inputname,'_input']);
    % set variable range to breakpoint range
    pTableInput.info = setrange(pTableInput.info,[min(Breakpoints) max(Breakpoints)]);
end

bp = Breakpoints;
val = 0:length(bp)-1;
pNorm = cgnormaliser([inputname '_norm'], [bp(:) val(:)], pTableInput);
pNorm.info = pNorm.set('bplocks' , ones(size(bp(:))));

end


function createAllTables(C)
%createAllTables create all tables 

C.pTables = mbcpointer(1, sum(C.CreateTables));
C.pFill = mbcpointer(1, sum(C.CreateTables));
TableSize= cellfun(@length,C.BreakPoints);
tbl_n = 0;
for n = 1:length(C.pItems)
    if C.CreateTables(n)
        pExpr = C.pItems(n);
        tblname = C.TableName{n};
        tbl_n = tbl_n + 1;
        if C.pItems(n).isinport
            % create tables for inputs
            C.pTables(tbl_n) = iCreateLookupTwo(pExpr ,tblname,C.pNorm, C.pItems(n).getnomvalue,TableSize,C.TableRange{n});
        else
            %create table for model
            passign(C.pInputs, parrayeval(C.pInputs,@setvalue,{pveceval(C.pInputs,@getnomvalue)}))
            Y = evaluate(pExpr.info);
            if isnan(Y)
                Y = 0;
            end
            C.pTables(tbl_n) = iCreateLookupTwo(pExpr ,tblname,C.pNorm,Y,TableSize,C.TableRange{n});
        end
        C.pFill(tbl_n) = pExpr;
    end
end

end


function pTable = iCreateLookupTwo(pItem,TableName,pNorm,v,TableSize,Range)
%iCreateLookupTwo main creatopm routine for tables
%
% pTable = iCreateLookupTwo(pItem,TableName,pNorm,v,TableSize,Range)

tablevals = v*ones(TableSize);
pTable = cglookuptwo(TableName, tablevals, pNorm(2), pNorm(1));
LT = pTable.info;
LT = set(LT,'range',Range);
M = get(LT,'memory');
M(1).Information = sprintf('Table for ''%s''',pItem.getname);
LT = set(LT,'memory',M(1));
pTable.info = LT;
end