【问题标题】:Matlab if loop function, How to improve this function?Matlab if循环函数,如何改进这个函数?
【发布时间】:2015-04-30 07:05:51
【问题描述】:

我是 matlab 新手,我想弄清楚如何以一种智能/高效的方式编写以下函数。

首先,我创建一个矩阵y,其条目为HL,每一行都是预定义长度n 的排列。

例如,对于n=3,我得到矩阵y : H H H 的第一行。然后我想为每一行创建一个 size n x n 矩阵,其中例如条目 (1,2) 对应于将条目 y(1,1)y(1,2) 链接的变量,而条目 y(3,2) 对应于链接条目的变量y(1,3)y(1,2)。这可能吗?

function A1=mystupidfunction(s , n)
%n is the number of agents and s is the number of state, this function
%returns the matrix of influence. Stupid code must be improved to work for
%n agents

x = 'HL';                 %// Set of possible types
K = n;                      %// Length of each permutation

%// Create all possible permutations (with repetition) of letters stored in x
C = cell(K, 1);             %// Preallocate a cell array
[C{:}] = ndgrid(x);
y = cellfun(@(x){x(:)}, C);
y = [y{:}];

A1 = sym('A1',[n n], 'positive' );
syms H L A_HH A_HL A_LH A_LL
for k=s
    for i=1:n
        for j=1:n
            if ( y(k,1)==H) && ( y(k,2)==H) && (y(k,3)==H)
                A1(i,j)=A_HH
            elseif ( y(k,1)==L) && ( y(k,2)==L) && (y(k,3)==L)
                A1(i,j)=A_LL
            elseif ( y(k,1)==H) && ( y(k,2)==L) && (y(k,3)==L)
                A1(1,1)=A_HH
                A1(1,2)=A_HL
                A1(1,3)=A_HL
                A1(2,1)=A_LH
                A1(3,1)=A_LH
                A1(2,2)=A_LL
                A1(2,3)=A_LL
                A1(3,3)=A_LL
                A1(3,2)=A_LL
            elseif ( y(k,1)==H) && ( y(k,2)==H) && (y(k,3)==L)
                A1(1,1)=A_HH
                A1(1,2)=A_HH
                A1(1,3)=A_HL
                A1(2,1)=A_HH
                A1(3,1)=A_LH
                A1(2,2)=A_HH
                A1(2,3)=A_HL
                A1(3,3)=A_LL
                A1(3,2)=A_LH
            elseif ( y(k,1)==L) && ( y(k,2)==L) && (y(k,3)==H)
                A1(1,1)=A_LL
                A1(1,2)=A_LL
                A1(1,3)=A_LH
                A1(2,1)=A_LL
                A1(3,1)=A_LH
                A1(2,2)=A_LL
                A1(2,3)=A_LH
                A1(3,3)=A_HH
                A1(3,2)=A_HL
            elseif ( y(k,1)==L) && ( y(k,2)==H) && (y(k,3)==H)
                A1(1,1)=A_LL
                A1(1,2)=A_LH
                A1(1,3)=A_LH
                A1(2,1)=A_HL
                A1(3,1)=A_HL
                A1(2,2)=A_HH
                A1(2,3)=A_HH
                A1(3,3)=A_HH
                A1(3,2)=A_HH
            elseif ( y(k,1)==L) && ( y(k,2)==H) && (y(k,3)==L)
                A1(1,1)=A_LL
                A1(1,2)=A_LH
                A1(1,3)=A_LL
                A1(2,1)=A_HL
                A1(3,1)=A_LL
                A1(2,2)=A_HH
                A1(2,3)=A_HL
                A1(3,3)=A_LL
                A1(3,2)=A_LH

            elseif ( y(k,1)==H) && ( y(k,2)==L) && (y(k,3)==H)
                A1(1,1)=A_HH
                A1(1,2)=A_HL
                A1(1,3)=A_HH
                A1(2,1)=A_LH
                A1(3,1)=A_HH
                A1(2,2)=A_LL
                A1(2,3)=A_HL
                A1(3,3)=A_HH
                A1(3,2)=A_HL
            else A(i,j)=0
            end
        end
    end
end

比如n=3s=1,那么函数返回:

A =

[ A_HH, A_HH, A_HH]
[ A_HH, A_HH, A_HH]
[ A_HH, A_HH, A_HH]

注释:

C = cell(K, 1);             %// Preallocate a cell array
[C{:}] = ndgrid(x);         %// Create K grids of values
y = cellfun(@(x){x(:)}, C); %// Convert grids to column vectors
y = [y{:}];

输出适用于 n=3 : y =

HHH
LHH
HLH
LLH
HHL
LHL
HLL
LLL

s 只是一个标量,表示矩阵 y 中的行数(对应于“状态”)

【问题讨论】:

  • 你需要缩进你的代码..我提交了一个编辑,在matlab的编辑器工具栏中有一个缩进部分在插入和注释下..如果你选择了所有你的代码然后点击绿色按钮为你做缩进..
  • 我在这里看到了一些改进的潜力,但是为了不弄乱你需要更好地解释某些部分的代码。 1) ndgrid('HL') 应该是什么,为什么你使用 ascii 等效于 72 (H) 和 76 (L)? (也许因为 H 和 L 更容易记住?) 2)s 应该是向量还是标量?在任何情况下,您都需要一个 for 循环 for k=s,因为您只存储最后一次迭代的值 (k=s(end))。 3)您是否尝试过运行此代码?我看到很多代码可能会崩溃的地方。在这种情况下,您应该提供错误消息。
  • @patrik 谢谢,我将通过编辑我的问题来回答你,我似乎无法将代码粘贴到评论中
  • @patrik 非常感谢,我没有使用 ascii,我的问题中有两种状态,我称之为 H 和 L(我可以称它们为 0 和 1)。我的代码实际上给了我没有错误消息的矩阵 A,但是运行时间很长,它只适用于 n=3(不是很聪明)。

标签: matlab function matrix


【解决方案1】:

如果您只有HL 两个状态,正如您在评论中所说,您也可以使用01,所以是二进制逻辑。

要获得y 组合,只需以二进制数计数,直到获得正确的位数并将每个位转换为您决定的状态:

所以对于n=3 的订单,您将拥有:

n = 3 ;
a = de2bi( (0:2^n-1).' )

它为您提供所有 3 位二进制组合:

a =
     0     0     0
     1     0     0
     0     1     0
     1     1     0
     0     0     1
     1     0     1
     0     1     1
     1     1     1

如果您想要它们为 ascii 格式,则可以转换它们:

b = char( ones(size(a))* 'L') ;
b(~a) = 'H' ;

获得:

b =
HHH
LHH
HLH
LLH
HHL
LHL
HLL
LLL

因此,如果您想保留“ascii”字符逻辑(和输出),这可以完成这项工作:

function out = combiadjacent( k , n )

yb = de2bi( (0:2^n-1).' ) ;      %'// get the combinations
y = char( ones(size(yb))* 'L') ;
y(~yb) = 'H' ;

A = char( zeros(n,2*n) ) ;
for col=1:n
    Acol = [col col+1] + (col-1) ;
    A(:,Acol)   = [y(k,col)*ones(n,1)  y(k,:).'] ;
end

out = reshape( cellstr( reshape(A.',2,[]).' ) , n , n ).' ;

会给你一个单元格数组作为输出,如:

>> A = combiadjacent( 4 , 3 )
A = 
    'LL'    'LL'    'HL'
    'LL'    'LL'    'HL'
    'LH'    'LH'    'HH'

但是,如果您对确切的输出格式不挑剔,下面的解决方案可能会运行得更快:

function out = combiadjacent( k , n )

y = de2bi( (0:2^n-1).' ) ;         %'// get the combinations

b = ones(n,1)*y(k,:) ;

 %// use that to get a cell array of characters
out = cellfun( @(a,b) char(cat(2,a+65,b+65)) , num2cell(b) ,num2cell(b.'),'uni',0) ;

%'// or use that to get a cell array of double in output (even faster)
%// out = cellfun( @(a,b) cat(2,a,b) , num2cell(b) ,num2cell(b.'),'uni',0)

%// or that to get a cell array of boolean
%// out = cellfun( @(a,b) logical(cat(2,a,b)) , num2cell(b) ,num2cell(b.'),'uni',0) ;

哪个会给你

>> A = combiadjacent( 4 , 3 )
A = 
    'BB'    'BB'    'AB'
    'BB'    'BB'    'AB'
    'BA'    'BA'    'AA'

注意:无论您选择何种解决方案,为k 添加检查条件以确保用户不会请求不存在的行是谨慎的做法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多