매트릭스 변환;개념과 이론, 실무적으로 학습할 수 있는 무료 리소스가 있나요?[닫은]

StackOverflow https://stackoverflow.com/questions/1016284

문제

저는 최근 좌표에서 차트와 그래프를 렌더링하는 데 재미를 느꼈고, 좌표 공간을 변환하기 위해 행렬을 사용하는 것에 매료되었습니다.

나는 2차원 좌표 공간을 성공적으로 확장하고 반전시킬 수 있었지만 이제는 식욕이 돋보입니다.:)

특히 2차원 및 3차원 공간에 적용되는 행렬, 행렬 수학에 대한 명확하고 유익한 (무료) 교육 자료를 어디에서 얻을 수 있습니까?

도움이 되었습니까?

해결책

원래 답변: 수학 강좌에서 일반적으로 행렬을 소개하는 방식이 마음에 드실지 모르겠습니다.프로그래머로서 당신은 괜찮은 3D 그래픽 책을 구입하는 것이 더 행복할 것입니다.확실히 매우 구체적인 3x3 행렬이 있어야 합니다.또한 당신을 가르칠 사람들을 찾아보세요 사영 변환 (사영 기하학은 저차원 기하학의 매우 아름다운 영역이며 프로그래밍하기 쉽습니다).

Python 3를 사용한 행렬 수학 미니 강좌

내용물:

  1. 행렬 [Vector, __add__, reflect_y, rotate, dilate, transform]
  2. 행렬:과부하됨 [Matrix, __add__, __str__, __mul__, zero, det, inv, __pow__]
  3. 보너스:복소수
  4. 행렬:(R) 진화.이미 제작 중입니다(마지막에 요약이 있습니다).

머리말: 내 강의 경험에 비추어 볼 때 다른 사람들이 참조하는 강좌가 매우 좋다고 생각합니다. 과정.즉, 목표가 수학자처럼 행렬을 이해하는 것이라면 반드시 전체 과정을 이수해야 한다는 의미입니다.그러나 귀하의 목표가 좀 더 겸손하다면 귀하의 요구에 더 적합한 것을 시도해 보겠습니다. (그러나 여전히 많은 이론적 개념을 전달하려는 목표로 작성되었으며, 이는 내 원래 조언과 모순됩니다.)

사용하는 방법:

  • 이번 포스팅은 길어요.이것을 인쇄하고 하루에 한 부분처럼 천천히 진행하는 것을 고려할 수 있습니다.
  • 코드는 필수입니다.프로그래머를 위한 강좌입니다.운동도 필수적이다.
  • 당신은해야 코드 컴패니언을 살펴보세요 여기에는 이 모든 코드와 그 이상의 내용이 포함되어 있습니다.
  • "1개 가격에 2개" 특별 상품입니다.여기에서 Python 3도 배울 수 있습니다.그리고 복소수.
  • 나는 이 글을 읽으려는 모든 시도를 높이 평가할 것입니다(공식적으로 가장 긴 게시물에 대한 자격이 있습니까?). 이해하지 못하는 부분이 있으면(그리고 이해하는 경우에도) 자유롭게 의견을 말해주세요.

1.행렬

벡터

행렬 앞에 벡터가 옵니다.당신은 2차원 및 3차원 벡터를 처리하는 방법을 확실히 알고 있습니다.

class Vector:
    """This will be a simple 2-dimensional vector.

    In case you never encountered Python before, this string is a
    comment I can put on the definition of the class or any function.
    It's just one of many cool features of Python, so learn it here!

    """

    def __init__(self, x, y): 
        self.x = x
        self.y = y

이제 당신은 쓸 수 있습니다

v = Vector(5, 3)
w = Vector(7, -1)

하지만 그 자체로는 별로 재미가 없습니다.더 유용한 메소드를 추가해 보겠습니다.

    def __str__(self: 'vector') -> 'readable form of vector':
        return '({0}, {1})'.format(self.x, self.y)

    def __add__(self:'vector', v: 'another vector') -> 'their sum':
        return Vector(self.x + v.x, self.y + v.y)

    def __mul__(self:'vector', number: 'a real number') -> 'vector':
        '''Multiplies the vector by a number'''
        return Vector(self.x * number, self.y * number)

이제 다음과 같이 작성할 수 있으므로 상황이 더욱 흥미로워집니다.

print(v + w * 2)

그리고 답을 얻으세요 (19, 1) 벡터로 멋지게 인쇄됩니다(예제가 낯설다면 이 코드가 C++에서 어떻게 보일지 생각해 보세요).

변환

이제 글을 쓸 수 있게 되었어요 1274 * w 하지만 그래픽에는 더 많은 벡터 연산이 필요합니다.그 중 일부는 다음과 같습니다.벡터를 뒤집을 수 있습니다 (0,0) 포인트, 당신은 그것을 주변에 반영할 수 있습니다 x 또는 y 축을 시계 방향이나 시계 반대 방향으로 회전할 수 있습니다(여기에 그림을 그리는 것이 좋습니다).

몇 가지 간단한 작업을 수행해 보겠습니다.

    ...

    def flip(self:'vector') -> 'vector flipped around 0':
        return Vector(-self.x, -self.y)

    def reflect_x(self:'vector') -> 'vector reflected around x axis':
        return Vector(self.x, -self.y)


print(v.flip(), v.reflect_x())
  • 질문: 표현이 가능한가요? flip(...) 아래의 작업을 사용하고 있습니까?는 어때 reflect_x?

이제 내가 왜 생략했는지 궁금할 것입니다. reflect_y.글쎄요, 잠시 멈추고 자신만의 버전을 작성해 보시기 바랍니다.알겠습니다. 내 것은 다음과 같습니다.

    def reflect_y(self:'vector') -> 'vector reflected around y axis':
        return self.flip().reflect_x()

이 함수가 어떻게 계산하는지 살펴보면 실제로는 매우 사소합니다.그런데 갑자기 놀라운 일이 일어났습니다.기존 변환만 사용하여 변환을 작성할 수 있었습니다. flip 그리고 reflect_x.내가 걱정하는 모든 것에 대해 reflect_y 액세스하지 않고도 파생 클래스에서 정의할 수 있습니다. x 그리고 y 그리고 그것은 여전히 ​​​​작동할 것입니다!

수학자들은 이러한 함수를 호출합니다. 운영자.그들은 이렇게 말할 것이다 reflect_y 다음으로 얻은 연산자입니다. 구성 운영자 수 flip 그리고 reflect_x 이것은에 의해 표시됩니다 reflect_y = flip ○ reflect_x (유니코드 기호인 작은 원이 보일 것입니다. 25CB).

  • 메모: 나는 아주 자유롭게 사용할 것이다. = 이제부터 기호는 위 단락에서와 같이 두 작업이 동일한 결과를 생성함을 나타냅니다.이는 "수학적 =", 어느 프로그램으로 표현할 수 없다.

그래서 만약 내가 그렇게 한다면

print(v.reflect_y())

나는 결과를 얻는다 (-5, 3).가서 그려보세요!

  • 질문: 구성을 고려해보세요 reflect_y ◦ reflect_y.이름을 어떻게 짓겠습니까?

회전

이러한 작업은 훌륭하고 유용했지만 회전을 도입하는 데 왜 그렇게 느린지 궁금할 것입니다.알겠습니다. 다음과 같습니다.

    def rotate(self:'vector', angle:'rotation angle') -> 'vector':
        ??????

이 시점에서 벡터를 회전하는 방법을 알고 있다면 계속해서 물음표를 채워야 합니다.그렇지 않으면 한 가지 더 간단한 경우에 대해 양해해 주시기 바랍니다.시계 반대 방향 회전 90 도.이것은 종이에 그리는 것이 어렵지 않습니다.

    def rotate_90(self:'vector') -> 'rotated vector':
        new_x = - self.y
        new_y =   self.x
        return Vector(new_x, new_y)

견딜 수 없는

x_axis = Vector(1, 0)
y_axis = Vector(0, 1)

print(x_axis.rotate_90(), y_axis.rotate_90())

이제 준다 (0, 1) (-1, 0).직접 실행해보세요!

  • 질문: 증명해 보세요 flip = rotate_90 ◦ rotate_90.

어쨌든 비밀 재료를 더 이상 숨기지 않겠습니다.

import math   # we'll need math from now on
  ...

class Vector:

      ...

    def rotate(self:'vector', angle:'rotation angle') -> 'rotated vector':
        cos = math.cos(angle)
        sin = math.sin(angle)
        new_x = cos * self.x - sin * self.y
        new_y = sin * self.x + cos * self.y
        return Vector(new_x, new_y)

이제 다음과 같은 내용을 시도해 보겠습니다.

print(x_axis.rotate(90), y_axis.rotate(90))

이전과 같은 결과를 기대한다면, (0, 1) (-1, 0), 당신은 실망하게 될 것입니다.해당 코드는 다음을 인쇄합니다.

(-0.448073616129, 0.893996663601) (-0.893996663601, -0.448073616129)

그리고 얘야, 그거 못생겼어!

  • 표기법: 연산을 적용했다고 할게요 rotate(90) 에게 x 위의 예에서.우리가 얻은 지식은 다음과 같습니다. rotate(90) != rotate_90.

  • 질문: 여기 뭔 일 있었 니?표현하는 방법 rotate_90 측면에서 rotate?표현하는 방법 flip 측면에서 rotate?

팽창

이러한 회전은 확실히 유용하지만 2D 그래픽을 수행하는 데 필요한 전부는 아닙니다.다음 변환을 고려하십시오.

    def dilate(self:'vector', axe_x:'x dilation', axe_y:'y dilation'):
        '''Dilates a vector along the x and y axes'''
        new_x = axe_x * self.x
        new_y = axe_y * self.y
        return Vector(new_x, new_y)

이것 dilate 일이 확장된다 x 그리고 y 축을 다른 방식으로 사용할 수 있습니다.

  • 운동: 에 물음표를 채워보세요 dilate(?, ?) = flip, dilate(?, ?) = reflect_x.

나는 이것을 사용할 것이다 dilate 수학자들이 부르는 것을 보여주는 함수 교환성:즉, 모든 매개변수 값에 대해 a, b, c, d 당신은 그것을 확신할 수 있습니다

dilate(a, b) ◦ dilate(c, d) = dilate(c, d) ◦ dilate(a, b)
  • 운동: 증명해 보세요.또한 아래의 가능한 모든 매개변수 값에 대해 유지된다는 것이 사실입니까?

    • rotate(a) ◦ rotate(b) = rotate(b) ◦ rotate(a)
    • dilate(a, b) ◦ rotate(c) = rotate(c) ◦ dilate(a, b)
    • rotate(a) ◦ __mul__(b) = __mul__(b) ◦ rotate(a)

행렬

여기 주변에 있던 모든 것을 요약해 보겠습니다. 벡터의 연산자 x

  • flip, reflect_x, *, rotate(angle), dilate(x, y)

다음과 같은 정말 말도 안되는 것들을 만들 수 있습니다.

  • flip ◦ rotate(angle) ◦ dilate(x, y) ◦ rotate(angle_2) ◦ reflect_y + reflect_x = ???

점점 더 복잡한 표현을 만들수록 가능한 모든 표현을 갑자기 유용한 형식으로 줄이는 일종의 순서를 원하게 됩니다.두려워하지 마세요!마술처럼 위 형식의 모든 표현은 다음과 같이 단순화될 수 있습니다.

    def ???(self:'vector', parameters):
        '''A magical representation of a crazy function'''
        new_x = ? * self.x + ? * self.y
        new_y = ? * self.x + ? * self.y
        return Vector(new_x, new_y)

대신에 숫자 및/또는 매개변수를 사용하여 ?에스.

  • 예: '?'의 가치를 알아보십시오. are for __mul__(2) ◦ rotate(pi/4)
  • 다른 예시: 같은 질문 dilate(x, y) ◦ rotate(pi/4)

이를 통해 우리는 범용 함수를 작성할 수 있습니다.

    def transform(self:'vector', m:'matrix') -> 'new vector':
        new_x = m[0] * self.x + m[1] * self.y
        new_y = m[2] * self.x + m[3] * self.y
        return Vector(new_x, new_y)

이는 4개의 숫자 튜플을 취합니다. 행렬, 그리고 적용하다 벡터로 x.예는 다음과 같습니다.

rotation_90_matrix = (0, -1, 1, 0)
print(v, v.rotate_90(), v.transform(rotation_90_matrix))

인쇄하는 것 (5, 3) (-3, 5) (-3, 5).신청하시면 참고하세요 transform 원산지에 대한 행렬을 사용하면 여전히 원산지가됩니다.

origin = Vector(0, 0)
print(origin.transform(rotation_90_matrix))
  • 운동: 튜플은 무엇입니까? m 설명하는 flip, dilate(x, y), rotate(angle)?

우리가 그 사람과 헤어지면서 Vector 수업 중 벡터 수학 지식과 Pythonic 기술을 모두 테스트하려는 사람들을 위한 연습은 다음과 같습니다.

  • 마지막 전투: 에 추가 Vector 당신이 생각해 낼 수 있는 모든 벡터 연산을 분류하십시오(벡터에 대해 얼마나 많은 표준 연산자를 오버로드할 수 있습니까?내 답변을 확인하세요).

2.행렬:과부하됨

이전 섹션에서 알아냈듯이 행렬은 벡터 연산을 간단한 방법으로 인코딩할 수 있는 약칭으로 생각할 수 있습니다.예를 들어, rotation_90_matrix 90도 회전을 인코딩합니다.

매트릭스 객체

이제 우리는 벡터에서 매트릭스로주의를 돌리면서 매트릭스에 대한 클래스도 있어야합니다.게다가 그 기능에는 Vector.transform(...) 매트릭스의 역할에 대해서는 다소 잘못 표현되었습니다.그것은 더 일반적입니다 m 벡터가 변경되는 동안 수정되어야 하므로 이제부터 변환은 행렬 클래스의 메서드가 됩니다.

class Matrix:

    def __init__(self:'new matrix', m:'matrix data'):
        '''Create a new matrix.

        So far a matrix for us is just a 4-tuple, but the action
        will get hotter once The (R)evolution happens!

        '''
        self.m = m

    def __call__(self:'matrix', v:'vector'):
        new_x = self.m[0] * v.x + self.m[1] * v.y
        new_y = self.m[2] * v.x + self.m[3] * v.y
        return Vector(new_x, new_y)

파이썬을 모르신다면, __call__ 의 의미가 오버로드됩니다. (...) 행렬의 경우 행렬에 대한 표준 표기법을 사용할 수 있습니다. 연기 벡터에.또한 행렬은 일반적으로 단일 대문자를 사용하여 작성됩니다.

J = Matrix(rotation_90_matrix)
print(w, 'rotated is', J(w))
  • 운동: 이전 연습의 행렬을 사용하여 이 예를 반복하세요.

덧셈

이제 행렬로 무엇을 할 수 있는지 알아봅시다.그 매트릭스를 기억하세요 m 실제로는 벡터에 대한 연산을 인코딩하는 방법일 뿐입니다.두 가지 기능에 대해 참고하세요 m1(x) 그리고 m2(x) 새 함수를 만들 수 있습니다(다음을 사용하여 람다 표기법) m = lambda x: m1(x) + m2(x).다음과 같은 경우에 밝혀졌습니다. m1 그리고 m2 행렬에 의해 인코딩되었으며, 이것을 인코딩할 수도 있습니다 m 행렬 사용!

  • 운동: 이 진술로 인해 발생할 수 있는 어려움을 생각해 보십시오.

다음과 같이 데이터를 추가하기만 하면 됩니다. (0, 1, -1, 0) + (0, 1, -1, 0) = (0, 2, -2, 0).다음은 매우 유용하고 매우 Python적인 기술을 사용하여 Python에서 두 개의 튜플을 추가하는 방법입니다.

    def __add__(self:'matrix', snd:'another matrix'):
        """This will add two matrix arguments.

        snd is a standard notation for second argument.
        (i for i in array) is Python's powerful list comprehension.
        zip(a, b) is used to iterate over two sequences together

        """

        new_m = tuple(i + j for i, j in zip(self.m, snd.m))
        return Matrix(new_m)

이제 다음과 같은 표현식을 작성할 수 있습니다. J + J 또는 J + J + J, 그러나 결과를 보려면 매트릭스를 인쇄하는 방법을 알아야 합니다.가능한 방법은 4-튜플 숫자를 인쇄하는 것이지만, 다음에서 힌트를 얻겠습니다. Matrix.__call__ 숫자를 다음과 같이 구성해야 하는 함수 2x2 차단하다:

    def as_block(self:'matrix') -> '2-line string':
        """Prints the matrix as a 2x2 block.

        This function is a simple one without any advanced formatting.
        Writing a better one is an exercise.

        """

        return ('| {0} {1} |\n' .format(self.m[0], self.m[1]) +
                '| {0} {1} |\n' .format(self.m[2], self.m[3]) )

이 기능이 실제로 작동하는 모습을 보면 개선의 여지가 있다는 것을 알 수 있습니다.

print((J + J + J).as_block())
  • 운동: 더 좋은 함수를 작성해 보세요 Matrix.__str__ 숫자를 반올림하여 고정 길이의 필드에 인쇄합니다.

이제 회전을 위한 행렬을 작성할 수 있습니다.

def R(a: 'angle') -> 'matrix of rotation by a':
    cos = math.cos(a)
    sin = math.sin(a)
    m = ( ????? )
    return Matrix(m)
  • 운동: 다음에 대한 코드를 검사합니다. Vector.rotate(self, angle) 그리고 물음표를 채워보세요.테스트

    from math import pi        
    print(R(pi/4) + R(-pi/4))
    

곱셈

단일 매개변수 함수로 할 수 있는 가장 중요한 일은 함수를 구성하는 것입니다. f = lambda v: f1(f2(v)).이를 행렬로 미러링하는 방법은 무엇입니까?이를 위해서는 우리가 어떻게 Matrix(m1) ( Matrix(m2) (v)) 공장.확대해 보면 알겠지만

m(v).x = m1[0] * (m2[0]*v.x + m2[1]*v.y) + m1[1] * (m2[2]*v.x + m2[3]*v.y)

그리고 마찬가지로 m(v).y, 괄호를 열면 의심스럽게 비슷하게 보입니다. Matrix.__call__ 새로운 튜플을 사용하여 m, 그렇게 m[0] = m1[0] * m2[0] + m1[2] * m2[2].따라서 이것을 새로운 정의에 대한 힌트로 삼아 보겠습니다.

    def compose(self:'matrix', snd:'another matrix'):
        """Returns a matrix that corresponds to composition of operators"""

        new_m = (self.m[0] * snd.m[0] + self.m[1] * snd.m[2],
                 self.m[0] * snd.m[1] + self.m[1] * snd.m[3],
                 ???,
                 ???) 
        return Matrix(new_m)
  • 운동: 여기에 물음표를 채워보세요.테스트해 보세요

    print(R(1).compose(R(2)))
    print(R(3))
    
  • 수학 연습: 증명해 보세요 R(a).compose(R(b)) 항상 같다 R(a + b).

이제 진실을 말하겠습니다.이것 compose 함수는 실제로 수학자들이 결정한 방식입니다. 곱하다 행렬.이는 표기법으로 의미가 있습니다. A * B 연산자를 설명하는 행렬입니다. A ○ B, 그리고 다음에 살펴보겠지만, 이것을 '곱셈'이라고 부르는 더 깊은 이유도 있습니다.

Python에서 곱셈을 사용하기 위해 해야 할 일은 다음과 같이 순서를 지정하는 것뿐입니다. Matrix수업:

    class Matrix:

          ...

        __mul__ = compose
  • 운동: 컴퓨팅 (R(pi/2) + R(pi)) * (R(-pi/2) + R(pi)).먼저 종이에서 스스로 답을 찾아보세요.

규칙 + 그리고 *

다음에 해당하는 행렬에 대한 좋은 이름을 만들어 보겠습니다. dilate(a, b) 운영자.이제 아무 문제 없어 D(a, b), 그러나 나는 표준 표기법을 소개하기 위해 기회를 사용하겠습니다.

def diag(a: 'number', b: 'number') -> 'diagonal 2x2 matrix':
    m = (a, 0, 0, b)
    return Matrix(m)

노력하다 print(diag(2, 12345)) 왜 이름이 붙었는지 알아보려면 대각선 행렬.

연산의 구성이 항상 교환 가능한 것은 아니라는 것이 이전에 밝혀졌기 때문에, * 연산자는 행렬에 대해 항상 교환 가능한 것은 아닙니다.

  • 운동: 돌아가서 새로 고침 교환성 필요한 경우 것.그런 다음 행렬의 예를 들어보세요. A, B, 에서 만들어진 R 그리고 diag, 그렇게 A * B 같지 않다 B * A.

숫자의 곱셈은 항상 교환 가능하기 때문에 이것은 다소 이상합니다. compose 정말 불릴만하다 __mul__.여기에는 꽤 많은 규칙이 있습니다. + 그리고 * 하다 풀다:

  1. A + B = B + A
  2. A * (B + C) = A * B + A * C
  3. (A + B) * C = A * C + B * C
  4. (A * B) * C = A * (B * C)
  5. 라는 작업이 있습니다. A - B 그리고 (A - B) + B = A

    • 운동: 이 진술을 증명하십시오.정의하는 방법 A - B 측면에서 +, * 그리고 diag?무엇을 A - A 동일?메소드 추가 __sub__ 수업에 Matrix.계산하면 어떻게 될까요? R(2) - R(1)*R(1)?그것은 무엇과 같아야합니까?

그만큼 (A * B) * C = A * (B * C) 평등이 불린다 연관성 그리고 우리는 괄호를 형태의 표현에 넣는 것에 대해 걱정할 필요가 없기 때문에 특히 좋습니다. A * B * C:

print(R(1) * (diag(2,3) * R(2)))
print((R(1) * diag(2,3)) * R(2))

일반 숫자와 유사점을 찾아봅시다 0 그리고 1 그리고 빼기:

zero = diag(0, 0)
one = diag(1, 1)     

다음과 같이 쉽게 확인할 수 있는 추가 사항이 있습니다.

  1. A + zero = A
  2. A * zero = zero
  3. A * one = one * A = A

규칙은 짧은 이름이 있다는 의미에서 완전해집니다. 링 공리.따라서 수학자들은 행렬이 다음을 형성한다고 말할 것입니다. 반지, 그들은 실제로 항상 기호를 사용합니다 + 그리고 * 반지에 관해 이야기할 때 우리도 마찬가지입니다.

규칙을 사용하면 이전 섹션의 표현식을 쉽게 계산할 수 있습니다.

(R(pi/2) + R(pi)) * (R(-pi/2) + R(pi)) = R(pi/2) * R(-pi/2) +  ... = one + ...
  • 운동: 이걸 끝내세요.증명해 보세요 (R(a) + R(b)) * (R(a) - R(b)) = R(2a) - R(2b).

아핀 변환

행렬을 정의한 방법으로 돌아갈 시간입니다.이는 벡터로 수행할 수 있는 일부 작업에 대한 지름길이므로 실제로 그릴 수 있는 것입니다.다양한 평면 변형의 예를 보기 위해 펜을 가져가거나 다른 사람들이 제안한 자료를 살펴볼 수도 있습니다.

우리가 찾을 변환 중에서 아핀 것들, 어디서나 '똑같이' 보이는 사람들(굴곡 없음).예를 들어 어떤 지점을 중심으로 회전하는 경우 (x, y) 자격이 있습니다.이제 이것은 다음과 같이 표현할 수 없습니다. lambda v: A(v), 그러나 in은 다음과 같은 형식으로 작성할 수 있습니다. lambda v: A(v) + b 일부 매트릭스의 경우 A 그리고 벡터 b.

  • 운동: 찾기 A 그리고 b 그런 식으로 회전 pi/2 지점 주변 (1, 0) 위와 같은 형태를 가지고 있습니다.독특합니까?

모든 벡터에 대해 아핀 변환이 있다는 점에 유의하세요. 옮기다 벡터로.

아핀 변환은 모양을 늘리거나 확장할 수 있지만 모든 곳에서 동일한 방식으로 수행되어야 합니다.이제 어떤 도형의 면적도 변환에 따라 상수만큼 변한다는 것을 믿으시기 바랍니다.행렬로 주어진 변환의 경우 A 이 계수를 결정자 ~의 A 면적에 대한 공식을 두 벡터에 적용하여 계산할 수 있습니다. A(x_axis) 그리고 A(y_axis):

    def det(self: 'matrix') -> 'determinant of a matrix':
        return self.m[0]*self.m[3] - self.m[1] * self.m[2]

건강검진으로는, diag(a, b).det() 동일하다 a * b.

  • 운동: 이것을 확인하세요.인수 중 하나가 0이면 어떻게 되나요?부정적일 때는?

보시다시피 회전 행렬의 행렬식은 항상 동일합니다.

from random import random
r = R(random())
print (r, 'det =', r.det())

한 가지 흥미로운 점은 det 그것은 곱셈적이라는 것입니다(충분히 오랫동안 명상하면 정의에서 나온 것입니다).

A = Matrix((1, 2, -3, 0))
B = Matrix((4, 1, 1, 2))
print(A.det(), '*', B.det(), 'should be', (A * B).det())

행렬을 사용하여 할 수 있는 유용한 작업은 두 개의 선형 방정식으로 구성된 시스템을 작성하는 것입니다.

A.m[0]*v.x + A.m[1]*v.y = b.x
A.m[2]*v.x + A.m[3]*v.y = b.y

더 간단한 방법으로: A(v) = b.(일부) 고등학교에서 가르치는 대로 시스템을 해결해 보겠습니다.첫 번째 방정식을 곱합니다. A.m[3], 초 -A.m1 그리고 다음 문제를 해결하기 위해 추가합니다(의심스러운 경우 종이에 이 작업을 수행). v.x.

진짜 해봤으면 진작했어야지 A.det() * v.x = (A.m[3]) * b.x + (-A.m[1]) * b.y, 이는 항상 얻을 수 있음을 의미합니다. v 곱해서 b 다른 매트릭스에 의해.이 행렬은 ~의 A:

    def inv(self: 'matrix') -> 'inverse matrix':
        '''This function returns an inverse matrix when it exists,
        or raises ZeroDivisionError when it doesn't. 

        '''
        new_m = ( self.m[3] / self.det(), -self.m[1] / self.det(),
                  ????? )
        return Matrix(new_m)

보시다시피, 이 방법은 행렬의 행렬식이 0일 때 크게 실패합니다.정말로 원한다면 다음을 사용하여 이러한 기대를 잡을 수 있습니다.

try:
    print(zero.inv())
except ZeroDivisionError as e: ...
  • 운동: 메소드를 완료하십시오.다음과 같은 경우 역행렬이 존재하지 않음을 증명하세요. self.det() == 0.행렬을 나누는 방법을 작성하고 테스트해 보세요.역행렬을 사용하여 방정식 풀기 A(v) = x_axis (A 위에서 정의했습니다).

권한

역행렬의 주요 특성은 다음과 같습니다. A * A.inv() 항상 같음 one

  • 운동: 그건 직접 확인해 보세요.역행렬의 정의를 통해 왜 그렇게 되어야 하는지 설명해보세요.

그래서 수학자들은 다음과 같이 표현합니다. A.inv() ~에 의해 A-1.우리는 사용하기에 좋은 기능을 작성하는 것은 어떻습니까? A ** n 표기법 AN?순진한 것을 참고하세요 for i in range(n): answer *= self 사이클은 O (| n |)입니다. 이것은 복잡성으로 수행 할 수 있기 때문에 확실히 너무 느립니다. log |n|:

    def __pow__(self: 'matrix', n:'integer') -> 'n-th power':
        '''This function returns n-th power of the matrix.

        It does it more efficiently than a simple for cycle. A
        while loop goes over all bits of n, multiplying answer
        by self ** (2 ** k) whenever it encounters a set bit.

        ...
  • 운동: 이 기능에 세부사항을 입력하세요.테스트해 보세요

    X, Y = A ** 5, A ** -5 print (X, Y, X * Y, sep = '\n')

이 함수는 다음의 정수 값에만 작동합니다. n, 일부 행렬의 경우 제곱근(즉, 행렬)과 같은 분수 거듭제곱을 정의할 수도 있습니다. B 그렇게 B * B = A).

  • 운동: 의 제곱근을 구하세요 diag(-1, -1).이것이 유일한 대답입니까?다음과 같은 행렬의 예를 찾으세요. 그렇지 않다 제곱근을 가집니다.

보너스:복소수

여기서는 정확히 한 섹션의 주제를 소개하겠습니다!복잡한 주제라 실패할 가능성이 높으니 미리 양해 부탁드립니다.

첫째, 행렬이 있는 방식과 유사합니다. zero 그리고 one, 다음을 수행하여 실수로 행렬을 만들 수 있습니다. diag(number, number).해당 형식의 행렬은 덧셈, 뺄셈, 곱셈, 역전이 가능하며 그 결과는 숫자 자체에서 발생하는 결과를 모방합니다.따라서 모든 실제적인 목적을 위해 다음과 같이 말할 수 있습니다. diag(5, 5) ~이다 5.

그러나 Python은 아직 다음 형식의 표현식을 처리하는 방법을 모릅니다. A + 1 또는 5 * B 어디 A 그리고 B 행렬입니다.관심이 있으시다면 꼭 가서 다음 연습을 해보시거나 제가 구현한 것을 살펴보세요. 장식가);그렇지 않으면 그것이 구현되었다는 것만 알아두세요.

  • 전문가를 위한 연습: 연산자를 다음과 같이 변경합니다. Matrix 피연산자 중 하나가 행렬이고 다른 하나가 숫자인 모든 표준 연산에서 숫자는 자동으로 다음으로 변환됩니다. diag 행렬.또한 동등성에 대한 비교를 추가하십시오.

테스트 예시는 다음과 같습니다.

print( 3 * A - B / 2 + 5 )

이제 첫 번째 흥미로운 점은 다음과 같습니다. 복소수:매트릭스 J, 처음에 소개되었으며 다음과 같습니다. Matrix((0, 1, -1, 0)), 재미있는 속성이 있습니다. J * J == -1 (시도 해봐!).그 의미는 J 는 확실히 일반적인 숫자는 아니지만 방금 말했듯이 행렬과 숫자는 쉽게 혼합됩니다.예를 들어,

(1 + J) * (2 + J) == 2 + 2 * J + 1 * J + J * J = 1 + 3 * J

얼마 전에 나열된 규칙을 사용합니다.이것을 Python으로 테스트하면 어떻게 될까요?

(1 + J) * (2 + J) == 1 + 3*J

행복하게 말해야 해 True.다른 예시:

(3 + 4*J) / (1 - 2*J) == -1 + 2*J 

짐작할 수 있듯이 수학자들은 이러한 숫자를 '미친 숫자'라고 부르지 않지만 비슷한 작업을 수행합니다. 즉, 다음 형식의 표현식을 호출합니다. a + b*J 복소수.왜냐하면 그것은 여전히 ​​우리의 사례이기 때문입니다. Matrix 클래스를 사용하면 다음과 같은 작업을 꽤 많이 수행할 수 있습니다.덧셈, 뺄셈, 곱셈, 나눗셈, 거듭제곱 - 모두 이미 구현되어 있습니다!행렬이 놀랍지 않나요?

나는 다음과 같은 작업 결과를 인쇄하는 방법에 대한 질문을 간과했습니다. E = (1 + 2*J) * (1 + 3*J) 그래서 그것은 다음과 같은 표현처럼 보입니다. J 보다는 2x2 행렬.신중하게 검사하면 해당 행렬의 왼쪽 열을 형식으로 인쇄해야합니다. ... + ...J (좋은 점 하나 더:그것은 정확히 E(x_axis)!) 차이점을 아시는 분들 str() 그리고 repr() 다음과 같은 형식의 표현을 생성하는 함수의 이름을 지정하는 것이 당연하다는 것을 알아야 합니다. repr().

  • 운동: 함수 작성 Matrix.__repr__ 그것은 정확히 그렇게 할 것이고 그것으로 몇 가지 테스트를 시도할 것입니다. (1 + J) ** 3, 먼저 종이에 결과를 계산한 다음 Python으로 시도해 보세요.

  • 수학 문제: 결정 요인은 무엇입니까? a + b*J?당신이 무엇을 알고 있다면 절대값 복소수는 다음과 같습니다:그들은 어떻게 연결되어 있나요?절대값은 얼마인가? a?~의 a*J?

삼.행렬:(R) 진화

이 3부작의 마지막 부분에서 우리는 모든 것이 행렬이라는 것을 알게 될 것입니다.우리는 일반적인 것부터 시작하겠습니다 M x N 행렬을 사용하고, 벡터를 다음과 같이 생각할 수 있는 방법을 알아보세요. 1 x N 행렬과 숫자가 대각 행렬과 동일한 이유.참고로 우리는 복소수를 다음과 같이 탐구할 것입니다. 2 x 2 행렬.

마지막으로 행렬을 사용하여 아핀 변환과 투영 변환을 작성하는 방법을 배웁니다.

그래서 계획된 수업은 [MNMatrix, NVector, Affine, Projective].

여기까지 저를 참아주셨다면 이 속편에도 관심이 있으실 거라 생각합니다. 그래서 이 일을 계속해야 할지(그리고 어디에서, 제가 그 이상이라고 확신하기 때문에) 듣고 싶습니다. 단일 문서의 합리적인 길이로 간주됨)

다른 팁

MIT는 온라인으로 수학 과정의 자료를 많이 가지고 있습니다. http://ocw.mit.edu/ocwweb/mathematics/. 기본 사항이 다운되면 온라인으로 물리 메모도 있습니다.

이 MIT 문서는 변환의 기본에 대한 강력한 지식을 얻기위한 필수품입니다.

http://stellar.mit.edu/s/course/6/fa08/6.837/coursematerial/topics/topic2/lecturenotes/03_transform/03_transform.pdf

초보자를위한 최고의 책 중 하나는 Carl Meyer의 "매트릭스 분석 및 응용 선형 대수"입니다.

여기에서 전체 책을 온라인으로 볼 수 있습니다 (저작권 워터 마크가 있지만) :http://www.matrixanalysis.com/downloadchapters.html

5 장 PG를보고 싶을 수도 있습니다. 3 차원 컴퓨터 그래픽의 회전을 다루는 326-332

당신은보고 싶을 수도 있습니다 기하학적 선형 대수 I-Hsiung Lin, Yixiong Lin (ISBN : 9812560874). 이 책은 구체적으로 원하는대로 (2 차원 벡터 공간의 선형 변환)를 대상으로하며 전체적이고 진보적 인 세부 사항 (각 차원마다 300 페이지)으로 기하학적 접근 방식으로 처리합니다. 무료로 구매할 수는 없지만 좋은 대학 도서관에서 찾을 수 있어야합니다. 그렇지 않으면 책 파인더 상대적으로 겸손한 가격으로 얻을 수 있도록 도와야합니다.

Jim Hefferon의 무료 선형 대수 교과서는 정말 좋습니다. 너무 많은 무료 전자 책과 달리 Jim은 훌륭한 독자를 만들고 선형 대수에 대한 소개를하는 데 분명히 시간을 보냈습니다. 그것은 공식적인 수학적 글쓰기로 지나치게 부담이되지 않으며, 이는 종종 이론과 증거가 쉽게 이해할 수 없기 때문에 너무 조밀합니다. 또한 선형 대수의 실제 응용 분야에 대한 정말 훌륭한 예제가 포함되어 있습니다. 좌표 변환은 하나의 예일뿐입니다. 가격을 이길 수 없으며 연습에 대한 선택적 솔루션도 제공됩니다.

추신 : 좌표 변환이 당신의 사물이라면, 선형 대수로 완료된 후 차동 형상에 관심이있을 수 있습니다.

제가 찾아낸 정보들입니다.그 중 일부는 귀하에게 가치가 있을 수 있습니다:

이론:

(검색 중 "매트릭스" Google books에서는 많은 강의를 제공하고 있으며 그 중 일부는 변환과 직접적으로 연결되어 있습니다. 이것 는 첫 번째 결과 중 하나이지만, 더 확인해 보시기 바랍니다.)

나는 또한 당신에게 (이것이 맞는 단어인지는 모르겠습니다. 저는 단지 영어를 배우고 있습니다) 그 책들 중 하나에서 이런 종류의 정보를 찾아보라고 권합니다(비록 무료는 아니지만, 당신은 많은 부분을 찾을 수 있습니다) Google 도서의 오래된 책):

  1. 게임 프로그래밍 보석 7
  2. 게임 프로그래밍 보석 6
  3. 게임 프로그래밍 보석 5
  4. 게임 프로그래밍 보석 4
  5. 게임 프로그래밍 보석 3
  6. 게임 프로그래밍 보석 2
  7. 게임 프로그래밍 보석

각 항목에는 수학 보석에 대한 섹션이 있으며 거기에는 멋진 트릭이 많이 있습니다.그 책들은 1센트의 가치가 있습니다.

GPU 프로그래밍 보석도 있으므로 시도해 볼 수도 있습니다.

관행:

더 찾으면 여기에 링크를 편집하고 추가하겠습니다. 하지만 솔직히 말해서 Google을 사용하고 약 10분 만에 해당 링크를 찾았습니다.세계에서 가장 인기 있는 브라우저는 모든 것에 대한 데이터를 저장합니다. 물론 "모든 것"은 행렬도 의미합니다.

힘내 친구 야.

3D의 벡터와 함께 도트 제품과 크로스 제품을 사용하는 데 며칠을 보내야한다고 생각합니다. 그런 다음 Trig와 Vectors의 관계를 배우십시오. 그 후 행렬은 당신에게 훨씬 더 의미가 있습니다.

Gilbert Strang의 선형 대수에 관한 MIT-OCW의 코스. 놀라운 사람에 의한 놀라운 강의; 매트릭스에 대한 이해가 전적으로 프로그래밍 소스 (MATLAB)에서 파생된다면 선형 대수에 대한 코스는 분명히 매트릭스로 미친 일을 할 수있는 기본 사항을 제공합니다.

http://www.ocw.cn/ocwweb/mathematics/18-06spring-2005/videolectures/index.htm

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top