Found an issue with the book? Report it on Github.

배열 함수(Array Functions)

배열 함수(Array Functions)

모델리카에는 배열과 관련된 많은 함수가 있습니다. 이 섹션에서는 함수의 다양한 범주를 살펴보고 사용 방법을 설명합니다.

배열 구성 함수(Array Construction Functions)

이미 앞에서 배열 구조(Array Construction) 에 대해 이야기했습니다. 벡터와 행렬을 구축하는 데 사용할 수 있는 다양한 구문 구조를 살펴보았으며, 다른 행렬을 이용하여 새로운 행렬을 만드는 방법도 살펴보았습니다. 모델리카에는 이전에 제시된 기능에 대한 대안 또는 보완 기능으로 벡터, 행렬 및 고차원 배열을 구성하는 데 사용할 수 있는 여러 기능이 있습니다.

fill

fill 함수는 배열의 각 요소가 동일한 값을 갖는 배열을 만드는 데 사용합니다. fill 에 대한 인수는 다음과 같습니다.

fill(v, d1, d2, ..., dN)

여기서 v 는 배열의 각 요소에 부여할 값이고 나머지 인수는 각 차원의 크기입니다. 결과 배열의 요소는 v 와 같은 형태를 갖습니다.따라서 1.7 이라는 실수 값으로 5x7 배열을 채우려면 다음을 사용할 수 있습니다.

parameter Real x[5,7] = fill(1.7, 5, 7);

이렇게 하면 다음과 같이 채워진 행렬이 생성됩니다.

\begin{split}\left[ \begin{array}{ccccccc} 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 \\ 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 \\ 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 \\ 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 \\ 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 & 1.7 \end{array} \right]\end{split}

zeros

배열로 작업할 때 0으로 구성된 요소만 포함하는 배열을 만드는 것이 일반적인 경우 입니다.``zeros`` 를 사용하여 다음과 같이 배열을 초기화할 수 있습니다.

parameter Real y[2,3,5] = zeros(2, 3, 5);

ones

ones 함수는 결과 배열의 모든 요소가 1 값을 갖는다는 점을 제외하면 zeros 함수와 동일합니다. 예를 들면 다음과 같습니다.

parameter Real z[3,5] = ones(3, 5);

이렇게 하면 다음과 같이 채워진 행렬이 생성됩니다.

\begin{split}\left[ \begin{array}{ccccc} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \end{array} \right]\end{split}

identity

또 다른 일반적인 필요는 항등 행렬을 쉽게 구축하는 것입니다. 이 행렬의 대각선 요소는 모두 1 이고 다른 모든 요소는 0 입니다. 이것은 identity 으로 아주 쉽게 구성 할 수 있습니다. 따라서 identity 를 다음과 같이 호출합니다.

identity(5);

다음 행렬을 생성합니다.

\begin{split}\left[ \begin{array}{ccccc} 1 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 1 \\ \end{array} \right]\end{split}

diagonal

diagonal 함수는 대각선이 아닌 모든 요소가 0 인 행렬을 만드는 데 사용합니다. 대각선에 대한 유일한 인수는 대각선 요소의 값을 포함하는 배열입니다.따라서 다음 대각 행렬을 만들려면

\begin{split}\left[ \begin{array}{cccc} 2.0 & 0 & 0 & 0 \\ 0 & 3.0 & 0 & 0 \\ 0 & 0 & 4.0 & 0 \\ 0 & 0 & 0 & 5.0 \end{array} \right]\end{split}

다음 모델리카 코드를 사용할 수 있습니다.

diagonal({2.0, 3.0, 4.0, 5.0});

linspace

linspace 함수는 요소의 값이 동일한 간격으로 모두 선형으로 분포되는 벡터를 만듭니다.``linspace`` 함수는 다음과 같이 호출됩니다.

linspace(v0, v1, n);

여기서 v0 은 벡터의 첫 번째 요소 값이고 v1 은 벡터의 마지막 요소이며 n 은 벡터의 총 갯수 입니다.예를 들어 다음과 같이 linspace 를 호출합니다.

linspace(1.0, 5.0, 9);

아래와 같은 벡터를 생성합니다.

{1.0, 1.5, 2.0, 3.5, 3.0, 3.5, 4.0, 4.5, 5.0}

변환 함수(Conversion Functions)

다음 함수는 배열을 다른 배열로 변환하는 수단을 제공합니다.

scalar

scalar 함수는 다음과 같이 호출됩니다:

scalar(A)

여기서 A 는 각 차원의 크기가 1인 한 임의의 차원 수를 가진 배열입니다. scalar 함수는 배열에 포함된 (유일한) 스칼라 값을 반환합니다. 예를 들어,

scalar([5]) // Argument is a two-dimensional array (matrix)

그리고

scalar({5}) // Argument is a one-dimensional array (vector)

둘 다 스칼라 값 5 를 제공합니다.

vector

vector 함수는 다음과 같이 호출됩니다:

vector(A)

여기서 A 는 하나의 차원 만이라도 1 보다 큰 크기를 갖는 한 임의의 차원 수를 가진 배열입니다. vector 함수는 배열의 내용을 벡터( 단일 차원만 있는 배열)로 반환합니다.아래 예제와 같은 열 또는 행 행렬을 전달하면

vector([1;2;3;4]) // Argument is a column matrix

혹은

vector([1,2,3,4]) // Argument is a row matrix

이면, 아래 값이 돌아올 것입니다:

{1,2,3,4}

matrix

matrix 함수는 다음과 같이 호출됩니다:

matrix(A)

여기서 A 는 2개의 차원이 1 보다 큰 크기를 갖는 한 임의의 차원 수를 가진 배열입니다.``matrix`` 함수는 배열의 내용을 행렬(즉, 2차원 배열)으로 반환합니다.

수치적 연산(Mathematical Operations)

선형 대수학에는 벡터와 행렬에서 일반적으로 수행되는 다양한 유형의 수학 연산이 있습니다.모델리카는 이러한 작업 대부분을 수행하는 기능을 제공합니다.모델리카 방정식은 선형 대수학의 수학적 표현과 대응되는 형태로 매우 유사하게 보이도록 만들 수 있습니다.

덧셈, 뺄셈, 곱셈, 나눗셈, 지수와 같은 연산부터 시작해 봅시다. 대부분의 경우 이러한 연산은 스칼라, 벡터 및 행렬의 다양한 조합에 적용될 때 수학에서와 마찬가지로 작동합니다. 그러나 완전성과 참조를 위해 다음 표에 이러한 작업이 정의되는 방법이 요약되어 있습니다.

덧셈(Addition +)

Expression

Result

a + b

c = a + b

a_{i} + b_{i}

c_{i} = a_{i} + b_{i}

a_{ij} + b_{ij}

c_{ij} = a_{ij} + b_{ij}

a_{ijk} + b_{ijk}

c_{ijk} = a_{ijk} + b_{ijk}

뺄셈(Subtraction -)

Expression

Result

a - b

c = a - b

a_{i} - b_{i}

c_{i} = a_{i} - b_{i}

a_{ij} - b_{ij}

c_{ij} = a_{ij} - b_{ij}

a_{ijk} - b_{ijk}

c_{ijk} = a_{ijk} - b_{ijk}

곱셈(Multiplication * and .*)

곱셈 연산자에는 두 가지 유형이 있습니다. 첫 번째는 행렬-벡터 곱 과 같은 선형 대수의 일반적인 수학적 규칙을 따르는 일반 곱셈 연산자인 * 입니다. * 연산자의 동작은 다음 표에 요약되어 있습니다.

Expression

Result

a * b

c = a * b

a * b_i

c_i = a * b_i

a * b_{ij}

c_{ij} = a * b_{ij}

a * b_{ijk}

c_{ijk} = a * b_{ijk}

a_i * b

c_i = a_i * b

a_{ij} * b

c_{ij} = a_{ij} * b

a_{ijk} * b

c_{ijk} = a_{ijk} * b

a_{i} * b_{i}

c = \sum_i a_{i} * b_{i}

a_{i} * b_{ij}

c_j = \sum_i a_{i} * b_{ij}

a_{ij} * b_{j}

c_i = \sum_j a_{ij} * b_{j}

a_{ik} * b_{kj}

c_{ij} = \sum_k a_{ik} * b_{kj}

곱셈 연산자의 두 번째 유형은 합산을 수행하지 않고 단순히 모든 배열 요소에 연산자를 요소별로 적용하는 특별한 요소별 버전인 .* 입니다.

Expression

Result

a .* b

c = a * b

a_{i} .* b_{i}

c_{i} = a_{i} * b_{i}

a_{ij} .* b_{ij}

c_{ij} = a_{ij} * b_{ij}

a_{ijk} .* b_{ijk}

c_{ijk} = a_{ijk} * b_{ijk}

나눗셈(Division / and ./)

곱셈(Multiplication * and .*) 과 마찬가지로 두 개의 나눗셈 연산자가 있습니다. 첫 번째는 배열을 스칼라 값으로 나누는 데 사용할 수 있는 일반적인 나누기 연산자인 / 입니다.다음 표에는 이에 대한 동작이 요약되어 있습니다.

Expression

Result

a / b

c = a / b

a_i / b

c_i = a_i / b

a_{ij} / b

c_{ij} = a_{ij} / b

a_{ijk} / b

c_{ijk} = a_{ijk} / b

또한 요소별 버전의 나눗셈 연산자인 ./ 도 있으며, 그 동작은 다음 표에 요약되어 있습니다.

Expression

Result

a ./ b

c = a / b

a_{i} ./ b_{i}

c_{i} = a_{i} / b_{i}

a_{ij} ./ b_{ij}

c_{ij} = a_{ij} / b_{ij}

a_{ijk} ./ b_{ijk}

c_{ijk} = a_{ijk} / b_{ijk}

거듭제곱(Exponentiation ^ and .^)

곱셈(Multiplication * and .*)나눗셈(Division / and ./) 과 마찬가지로 지수 연산자는 두 가지 형태로 제공합니다. 첫 번째는 표준 지수 연산자인 ^ 입니다.표준 버전은 두 가지 방법으로 사용할 수 있습니다. 첫 번째는 하나의 스칼라를 다른 스칼라의 거듭제곱으로 위에 올려서 쓰는 것이며(즉, a ^ b ), 다른 하나는 정사각 행렬을 스칼라 거듭제곱으로 위에 올려서 쓰는 것입니다(즉, a_{ij} ^ b ).

거듭제곱의 다른 형식은 .^ 연산자로 표시되는 요소별 거듭제곱 형식입니다. 그 동작은 다음 표에 요약되어 있습니다.

Expression

Result

a .^ b

c = a^b

a_{i} .^ b_{i}

c_{i} = a_{i}^{b_{i}}

a_{ij} .^ b_{ij}

c_{ij} = a_{ij}^{b_{ij}}

a_{ijk} .^ b_{ijk}

c_{ijk} = a_{ijk}^{b_{ijk}}

등식(Equality =)

방정식을 구성하는 데 사용하는 등호 연산자는 =좌변과 우변의 차원 수가 동일하고 각 차원의 크기가 동일하면 스칼라 뿐 아니라 벡터에서도 사용할 수 있습니다.이 요구 사항이 충족된다고 가정하면 연산자는 단순히 요소별로 적용됩니다. 이는 왼쪽의 각 요소와 오른쪽의 해당 요소 사이에서 각각 연산자가 적용됨을 의미합니다.

대입(Assignment :=)

:= (할당) 연산자는 등식(Equality =) 연산자와 동일한 요소 방식으로 적용됩니다.

관계 연산자(Relational Operators)

모든 관계 연산자(and, or, not, >, >=, <=, ``< ``)는 등식(Equality =) 연산자와 동일한 요소 방식으로 적용됩니다.

전치(transpose)

transpose 함수는 행렬을 인수로 취하고 해당 행렬의 전치된 버전을 반환합니다.

외적(outerProduct)

outerProduct 함수는 두 개의 인수를 취하며, 각 인수는 벡터여야 하며 크기가 같아야 합니다. 이 함수는 두 벡터의 외적을 나타내는 행렬을 반환합니다.수학적으로 말하면 a b 가 같은 크기의 벡터라고 가정합니다. outerProduct(a,b) 를 호출하면 다음과 같이 요소가 정의된 행렬 c 가 반환됩니다.

c_{ij} = a_i * b_j

대칭(symmetric)

symmetric 함수는 정사각 행렬을 인수로 취합니다. 원래 행렬의 대각선 아래에 있는 모든 요소가 대각선 위에서 전치된 요소로 대체된 동일한 크기의 행렬을 반환합니다. 다시 말해,

\begin{split}b_{ij} = \mathtt{symmetric(a)} = \left\{ \begin{array}{c} a_{ij}\ \ \mathrm{if}\ i<=j \\ a_{ji}\ \ \mathrm{otherwise} \end{array} \right.\end{split}

비대칭(skew)

skew 함수는 세 가지 구성 요소가 있는 벡터를 사용하고 다음과 같은 비대칭 행렬을 반환합니다.

\begin{split}\mathtt{skew(x)} &= \left[ \begin{array}{ccc} 0 & -x_3 & x_2 \\ x_3 & 0 & -x_1 \\ -x_2 & x_1 & 0 \end{array} \right]\end{split}

교차(cross)

cross 함수는 두 개의 벡터(각각 3개의 구성 요소 포함)를 사용하고 다음 벡터(3개의 구성 요소 포함)를 반환합니다.

\begin{split}\mathtt{cross(x,y)} = \left\{ \begin{array}{c} x_2 y_3 - x_3 y_2 \\ x_3 y_1 - x_1 y_3 \\ x_1 y_2 - x_2 y_1 \end{array} \right\}\end{split}

축소 연산자(Reduction Operators)

축소 연산자는 배열을 스칼라 값으로 줄이는 연산자입니다.

min

min 함수는 배열을 받아 배열에서 가장 작은 값을 반환합니다. 예를 들어:

min({10, 7, 2, 11})  // 2
min([1, 2; 3, -4])   // -4

max

max 함수는 배열을 받아 배열에서 가장 큰 값을 반환합니다. 예를 들어:

max({10, 7, 2, 11})  // 11
max([1, 2; 3, -4])   // 3

sum

sum 함수는 배열을 받아 배열에 있는 모든 요소의 합을 반환합니다. 예를 들어:

sum({10, 7, 2, 11})  // 30
sum([1, 2; 3, -4])   // 2

product

product 함수는 배열을 받아 배열에 있는 모든 요소의 곱을 반환합니다. 예를 들어:

product({10, 7, 2, 11})  // 1540
product([1, 2; 3, -4])   // -24

잡다한 함수(Miscellaneous Functions)

ndims

ndims 함수는 배열을 인수로 취하고 해당 배열의 차원 수를 반환합니다. 예를 들어:

ndims({10, 7, 2, 11})  // 1
ndims([1, 2; 3, -4])   // 2

size

size 함수는 두 가지 다른 방식으로 호출될 수 있습니다.첫 번째 방법은 배열인 단일 인수를 사용하는 것입니다.이 경우 size 는 벡터의 각 구성 요소가 배열의 해당 차원 크기에 해당하는 벡터를 반환합니다.예를 들어:

size({10, 7, 2, 11})       // {4}
size([1, 2, 3; 3, -4, 5])  // {2, 3}

특정 차원 번호를 나타내는 선택적 추가 인수로 size 를 호출하는 것도 가능합니다. 이 경우 해당 특정 차원의 크기를 스칼라 정수로 반환합니다. 예를 들어,

size({10, 7, 2, 11}, 1)       // 4
size([1, 2, 3; 3, -4, 5], 1)  // 2
size([1, 2, 3; 3, -4, 5], 2)  // 3

벡터화(Vectorization)

이 섹션에서는 배열인 인수와 함께 작동하도록 설계된 모델리카의 수많은 함수에 대해 논의했습니다. 그러나 매우 일반적인 사용 사례는 벡터의 모든 요소에 요소별로 함수를 적용하는 것입니다.모델리카는 "벡터화"라는 기능을 통해 이 사용 사례를 지원합니다. 함수가 스칼라를 사용하도록 설계되었지만 대신 배열이 전달되는 경우 모델리카 컴파일러는 해당 함수를 벡터의 각 요소에 자동으로 적용합니다.

이것이 어떻게 작동하는지 이해하려면 먼저 abs 함수를 사용하는 일반 적인 경우를 살펴보면 됩니다.

abs(-1.5)   // 1.5

분명히 abs 는 일반적으로 스칼라 인수를 받아들이고 스칼라를 반환하는 것을 의미합니다. 그러나 모델리카에서는 다음과 같이 할 수도 있습니다.

abs({0, -1, 1, -2, 2})  // {0, 1, 1, 2, 2}

이 함수는 스칼라용으로 설계되었으므로 모델리카 컴파일러는 다음을 변환합니다.

abs({0, -1, 1, -2, 2})

내부에서는 아래와 같이 동작 합니다.

{abs(0), abs(-1), abs(1), abs(-2), abs(2)}

즉, 스칼라로 구성되어 있는 벡터에 적용되는 함수를 각각의 스칼라에 함수가 적용된 벡터로 변환합니다.

이 기능은 예상 스칼라 인수 중 하나 만 벡터인 경우 여러 인수를 사용하는 함수에서도 작동합니다.이 약간 더 복잡한 기능을 이해하려면 modulo 함수인 mod 를 생각해 보면 됩니다.이를 스칼라 인수에 적용하면 다음과 같이 동작 합니다.

mod(5, 2)  // 1

첫 번째 인수를 벡터로 변환하면 다음과 같은 결과를 얻습니다.

mod({5, 6, 7, 8}, 2)  // {1, 0, 1, 0}

즉, 다음과 같이 변환 됩니다.

mod({5, 6, 7, 8}, 2)

내부에서는 아래와 같이 동작 합니다.

{mod(5,2), mod(6,2), mod(7,2), mod(8,2)}

그러나 이 벡터화는 둘 이상의 스칼라 인수가 벡터로 표시되는 경우 적용되지 않습니다. 예를 들어 다음 식은 오류가 됩니다.

mod({5, 6, 7, 8}, {2, 3}) // Illegal

mod 는 두 개의 스칼라 인수를 예상하지만 두 개의 벡터 인수가 전달되었기 때문입니다.