매트랩은 기본적으로 벡터와 행렬 연산을 기반으로(주로) 동작합니다. 

따라서 매트랩 프로그래밍을 하는 과정중에 알고리즘에 의해 행렬이나 벡터의 원소 위치를 랜덤하게 바꾸어야(섞거나)하는 상황이 생기기도 합니다. 


 사실 포스팅 하기에는 매우 단순한 함수를 사용하지만 간혹 모르시는 분들이 계셔서 올려봅니다. 


그럼 간단한 예제와 함께 살펴보겠습니다.


예제 1) 


%일단 3x3 행렬을 만들어 보도록 하겠습니다. 

>> A=[1 2 3 ; 4 5 6 ; 7 8 9]

A= 

     1     2     3 
     4     5     6 
     7     8     9 

%이때, 행렬 A의 특정 위치의 원소값을 행과 열을 위치로 확인이 가능하지만 행렬의 전체 원소의 개수에 따라서 확인이 가능합니다. 

%매트랩은 기본적으로 열(column)벡터를 기준으로 연산하기 때문에 A(1)=1, A(3)=7, A(4)=2, etc., 와 같은 순서대로 배치가 됩니다.

%그럼 이어서 A 행렬의 첫번째 열의 순서를 랜덤하게 재배치 해보도록 하겠습니다.

>>idx = randperm(3)

idx = 

      3 1 2 

% randperm(n) 함수는 1에서 n(구간의 끝점 포함)까지의 정수로 구성된 난수 순열을 행 벡터로 

% 반환합니다. 즉, 내가 재배치하고 싶은 벡터의 길이(n)에 맞춰 난수를 생성하여 사용하면 됩니다.

>> A( : , 1 ) = A( idx, 1)

A = 

     7     2     3

     1     5     6

     4     8     9 

% A 행렬의 첫번째 열벡터의 원소 순서가 바뀐걸 확인할 수 있습니다. 

예제 2)


% 예제1을 응용하면 아까 말씀드린 행렬 원소 전체를 랜덤하게 재배치할 수 있습니다.

>> A=[1 2 3 ; 4 5 6 ; 7 8 9]

A= 

     1     2     3 
     4     5     6 
     7     8     9 

>>idx2 = randperm( numel(A) )

% randperm함수를 이용해서 A 행렬의 원소 개수에 맞춰 난수를 생성해봅시다. 이때 numel(A) 함수는 A의 전체 원소개수를 출력해줍니다. 

%즉, 여기서는 A행렬의 원소가 9개이니 numel(A)의 값은 9가 되겠죠? 

idx2 =

     5     1     8     2     9     7     3     4     6

>>A = A(idx2)

A = 

      5     1     6     4     9     3     7     2     8

% A(idx2) = A(5), A(1), A(8),... A(6) 을 의미하게 됩니다. 그러면 각각의 원소값을 확인해보면 A(5)=5, A(1)=1, A(8)=6,... 이 되니까 이 순서대로 재배치가 되겠죠?

% 하지만 우리가 원하는건 행벡터가 아닌 처음 3x3 행렬의 형태이니 다시 원래대로 돌려 놓습니다.

>>A = reshape(A,3,3)

A =
     5     4     7
     1     9     2
     6     3     8
% randperm 함수로 생성한 난수를 이용해 A 행렬의 원소를 랜덤하게 재배치 했습니다. 

예제 3)


%예제 1과 2에서 배운 내용을 한꺼번에 정리해서 아래와 같이 사용하시면 됩니다. 

A = reshape( A( randperm( numel(A) ) ), 3, 3);


이번 포스팅은 randperm 함수를 이용한 행렬 원소의 재배치에 대해서 알아보았습니다. 


 항상 느끼는 거지만 매트랩에는 정말 많은 함수들이 구현되어 있는 만큼 내가 모르는 함수도 많기 때문에 매트랩을 사용하시다가 막히시는 부분이 있으면 구글링을 먼저 해보시면 분명히 원하는 기능을 하는 함수나 혹은 기능 구현의 부분적인 함수를 찾으실 수 있습니다. 


 매트랩에는 기본적으로 optimization toolbox가 제공되어 사용할 수 있습니다. 

하지만 개인적으로 사용법이 직관적이지 않아 처음 사용하는데 애를 많이 먹었습니다. 

그러던 중 전에 들었던 최적화 이론 수업 교수님이 말씀해주신 CVX tool이 생각나서 찾아서 사용해봤는데 아직까지는 매트랩에서 제공되는 optimization toolbox 보다는 훨씬 더 사용하기 편하고 직관적인 것 같습니다. 


 CVX guide book에 있는 소개는 간단하게 다음과 같습니다.

CVX is a modeling system for constructing and solving disciplined convex programs (DCPs). CVX supports a number of standard problem types, including linear and quadratic programs (LPs/QPs), second-order cone programs (SOCPs), and semidefinite programs (SDPs). CVX can also solve much more complex convex optimization problems, including many involving nondifferentiable functions, such as `1 norms. You can use CVX to conveniently formulate and solve constrained norm minimization, entropy maximization, determinant maximization, and many other convex programs. 

As of version 2.0, CVX also solves mixed integer disciplined convex programs (MIDCPs) as well, with an appropriate integer-capable solver. 


 CVX 및 CVX 가이드 다운로드는 공식홈페이지에서 가능합니다.

다운로드 파일은 아래의 표를 참조하셔서 자신의 OS에 맞는 파일을 선택하시면 됩니다. 

(가이드북CVX_guide book.pdf



 다운로드 후 설치 방법은 매우 간단합니다. 해당 다운로드 파일의 압축을 푸신 후 아래의 그림과 같이 해당 폴더를 평소에 사용하시는 matlab path로 이동시키신 후에 그 폴더에서 'cvx_setup' 이라고 커맨드 명령어를 치시기만 하면 됩니다. 




Generate random points inside a circle with radius R





  이번 포스팅은 매트랩을 이용해 반지름이 R인 임의의 원을 생성하고 그 내부에 임의의 점(point)을 생성하는 방법에 대해 소개하겠습니다. 

 

 내용 및 과정 자체는 매우 심플하여 어렵지 않으나 이러한 구현은 다양한 연구분야에서 시스템 환경으로 활용됩니다. 실제로 제가 연구하고 있는 cognitive radio 시스템이나 localization에서 시뮬레이션을 위해 사용하고 있으며 이 외에 다른 여러 분야에서도 응용가능합니다. 



그림 1. 반지름이 10인 원



 그림 1과 같이 반지름(radius, r)이 10인 원을 먼저 그려보도록 하겠습니다. 일단 원을 그리기 위해선 기본적으로 원의 중점과 반지름을 설정해야 합니다. 


%% 원 그리기 

x1 = 0;  % 원 중심의 x좌표

y1 = 0;  % 원 중심의 y좌표

rc = 10; % 원의 반지름

[x,y] = cylinder(rc,200);  % z축의 파라미터를 입력할 경우 3차원의 원통형이 생성되지만 여기서는
                               % 2차원의 원만 표기하기 위해 z축 파라미터는 사용하지 않습니다. 

                               % 총 200개의 요소로 이루어진 원의 바운더리 좌표가 x, y에 각각 저장

figure(1)

plot(x(1,:)+x1, y(1,:)+y1, 'b', 'LineWidth', 2), hold on, grid on;

%앞에서 설정한 원의 중심값을 각 x, y좌표에 더해줌으로써 (x1,y1)을 중점으로 하는 반지름 10인 원을 그려주게 됩니다.'

title(['\fontsize{15}Radius=',num2str(rc)]);

xlabel('[m]'), ylabel('[m]');

코드 1. 반지름이 rc인 원 생성하기


위 코드대로 입력하시면 그림 1과 동일한 원을 그리실 수 있습니다. 

그러면 이제 그 원 안에 임의의 점(point)를 생성해보도록 하겠습니다. 



먼저 해당 코드를 짜기 전에 간단하게 어떤 방식으로 임의의 점을 생성시킬지 생각해봅시다.


1) 원의 중심을 기준으로 가장 멀리 떨어진 점의 거리(길이)를 반지름 이하가 되도록 한다. 

  -> rc값 이하의 임의의 숫자를 생성( r = rc*sqrt(rand) )

2) 원의 중심을 기준으로 임의의 라디안을 생성한다.

  -> gen_rad = 2*pi*rand;

3) 1)과 2)에서 생성한 값을 이용해 원의 중점(x1, y1)으로부터 임의의 위치에 point를 생성한다.

  -> x = r*cos(a)+x1, y = r*sin(a)+y1;


그러면 위에서 설명하 내용을 바탕으로 코딩을 진행해보도록 하죠. 


%% 반지름이 rc인 원 생성

x1 = 0;  % 원 중심의 x좌표

y1 = 0;  % 원 중심의 y좌표

rc = 10; % 원의 반지름

[x,y] = cylinder(rc,200);  % z축의 파라미터를 입력할 경우 3차원의 원통형이 생성되지만 여기서는 
                               % 2차원의 원만 표기하기 위해 z축 파라미터는 사용하지 않습니다. 

                               % 총 200개의 요소로 이루어진 원의 바운더리 좌표가 x, y에 각각 저장

figure(1)

plot(x(1,:)+x1, y(1,:)+y1, 'b', 'LineWidth', 2), hold on, grid on;

%앞에서 설정한 원의 중심값을 각 x, y좌표에 더해줌으로써 (x1,y1)을 중점으로 하는 반지름 10인 원을 그려주게 됩니다.'

title(['\fontsize{15}Radius=',num2str(rc)]);

xlabel('[m]'), ylabel('[m]');

%% 임의의 점 생성

a = 2*pi*rand( 1, length(x) );

r = sqrt( rand( 1, length(x) ) );

x11 = rc.*r.*cos(a) + x1;

y11 = rc.*r.*sin(a) + y1;

plot(x11, y11, '.r')

코드 2. 반지름이 rc인 원 생성 후 내부에 임의의 점 생성 


코드 2와 같이 코드 1의 뒤에 해당 부분을 추가해주면 모든 코딩이 끝나고 그림 2와 같이 나타나게 됩니다.


그림 2. 반지름이 rc인 원 내부에 임의의 포인트 생성


 

 또한 여기서 생성하는 임의의 포인트 숫자를 줄이거나 늘릴 수 있는데요, 코드 2부분에서 변수 ar의 길이를 생성할때 length(x)로 정의 했기 때문에 코드 1에서 생성한 원 바운더리의 포인트 갯수 (201개)와 동일하게 생성했습니다. 따라서, 임의의 점 개수를 늘리고 싶으시다면 해당 부분의 숫자를 조절해주시면 됩니다. 

 

다음번 포스팅은 위 예제를 이용한 푸아송 점 과정(Poisson point process) 예제를 진행해보도록 할게요 : )

+ Recent posts