Матричные преобразования;концепции и теория, есть ли бесплатные ресурсы для практического обучения?[закрыто]

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

Вопрос

В последнее время я получаю удовольствие от рендеринга диаграмм и графиков на основе координат, и меня увлекает использование матриц для преобразования координатных пространств.

Мне удалось успешно масштабировать и инвертировать двумерные координатные пространства, но теперь у меня разгорелся аппетит.:)

Где я могу найти понятные, информативные (бесплатные) учебные материалы по матрицам, матричной математике, особенно применительно к 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. Матрицы:Революция.Оно уже в разработке (в конце есть краткое содержание)

Предисловие: Основываясь на моем опыте преподавания, я считаю, что курсы, на которые ссылаются другие, очень хороши. курсы.Это означает, что если ваша цель — понять матрицы так, как это делают математики, вам обязательно следует пройти весь курс.Но если ваши цели более скромные, вот моя попытка создать что-то более адаптированное к вашим потребностям (но все же написанное с целью передать многие теоретические концепции, что в некоторой степени противоречит моему первоначальному совету).

Как использовать:

  • Этот пост длинный.Вы можете распечатать это и работать медленно, например, одну часть в день.
  • Код необходим.Это курс для программистов.Упражнения тоже необходимы.
  • Вам следует взгляните на компаньон по коду который содержит весь этот код и многое другое
  • Специальное предложение «2 по цене 1»:вы также можете изучить 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)

с некоторыми числами и/или параметрами вместо ?с.

  • Пример: Выясните, для чего нужны значения '?' __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)

который будет принимать любую четверку чисел, называемую матрица, и применять это в вектор 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, вы все равно получите origin:

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)

Если вы не знаете Python, __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, используя несколько очень полезных и очень питонических методов:

    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, но чтобы увидеть результаты, нам нужно выяснить, как напечатать матрицу.Возможный способ — напечатать кортеж из четырех чисел, но давайте возьмем подсказку из 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), но можно записать в виде 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.m.1 и добавьте (если сомневаетесь, сделайте это на листе бумаги), чтобы решить 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)

Как видите, этот метод явно терпит неудачу, когда определитель матрицы равен нулю.Если вы действительно хотите, вы можете поймать это ожидание с помощью:

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 обозначение для Aн?Обратите внимание, что наивный 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 являются матрицами.Если вам интересно, вам обязательно стоит пойти и выполнить следующее упражнение или посмотреть мою реализацию (в которой используется интересная функция Python под названием декоратор);в противном случае просто знайте, что это реализовано.

  • Упражнение для гуру: Измените операторы в 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 class, мы можем выполнять с ними довольно много операций:Сложение, вычитание, умножение, деление, степень – все это уже реализовано!Разве матрицы не удивительны?

Я упустил из виду вопрос о том, как распечатать результат операции, например 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?

3.Матрицы:Революция

В заключительной части этой трилогии мы увидим, что все представляет собой матрицу.Начнем с общего M x N матрицы и выясним, как векторы можно рассматривать как 1 x N матрицы и почему числа совпадают с диагональными матрицами.В качестве примечания мы рассмотрим комплексные числа как 2 x 2 матрицы.

Наконец, мы научимся писать аффинные и проективные преобразования с использованием матриц.

Итак, запланированные занятия [MNMatrix, NVector, Affine, Projective].

Я думаю, если бы вы смогли терпеть меня до сих пор, вы могли бы быть заинтересованы в этом продолжении, поэтому я хотел бы услышать, стоит ли мне продолжать это (и где, поскольку я почти уверен, что я за пределами того, что считается разумной длиной одного документа).

Другие советы

MIT размещает множество материалов своих курсов по математике в Интернете по адресу http://ocw.mit.edu. / OcwWeb / Математика / . После того, как вы ознакомитесь с основами, у них появятся заметки по физике онлайн.

Этот документ MIT является обязательным условием для получения глубоких знаний об основах трансформации.

http : //stellar.mit.edu/S/course/6/fa08/6.837/courseMaterial/topics/topic2/lectureNotes/03_transform/03_transform.pdf

Одна из лучших книг для начинающих - «Матричный анализ и прикладная линейная алгебра» Карла Мейера.

Вы можете просмотреть всю книгу онлайн здесь (хотя она имеет водяной знак авторского права): http://www.matrixanalysis.com/DownloadChapters.html

Возможно, вы захотите взглянуть на главу 5, стр. 326 - 332, который охватывает повороты в трехмерной компьютерной графике

Возможно, вы захотите взглянуть на геометрическую линейную алгебру , написанную I-Hsiung Lin, Yixiong Lin (ISBN: 9812560874). Книга специально ориентирована на то, что вы хотите (линейные преобразования 2-х и 3-х мерных векторных пространств) и рассматривает это с геометрическим подходом в полной, прогрессивной детализации (300 страниц для каждого измерения). Боюсь, что это не бесплатно, но вы должны найти его в любой хорошей университетской библиотеке. В противном случае Bookfinder должен помочь вам получить его по относительно скромной цене.

Джим Хефферон на свободе Линейная алгебра учебник действительно хороший.В отличие от многих бесплатных электронных книг, Джим явно нашел время, чтобы создать отличную читалку и введение в линейную алгебру.Он не слишком обременен формальной математической литературой, которая часто слишком насыщена теоремами и доказательствами, чтобы ее можно было легко понять.Он также содержит множество действительно превосходных примеров реального применения линейной алгебры - преобразования координат являются лишь одним из примеров.Вы не можете найти лучшую цену, к тому же в комплект входят дополнительные решения для упражнений.

P.S.Если вам нравятся преобразования координат, возможно, вас заинтересует дифференциальная геометрия после того, как вы закончите с линейной алгеброй.

Это та информация, которую я нашел.Некоторые из них могут быть для Вас ценны:

Теория:

(В поисках «Матрицы» в Google Books есть множество лекций, некоторые из которых напрямую связаны с трансформациями - этот это один из первых результатов, но я призываю Вас проверить больше.)

Я также призываю (не знаю, подходящее ли это слово, я только изучаю английский) вас поискать такого рода информацию в одной из этих книг (хотя они не бесплатны, но вы можете найти большую часть более старые в Google Книгах):

  1. Жемчужины игрового программирования 7
  2. Жемчужины игрового программирования 6
  3. Жемчужины игрового программирования 5
  4. Жемчужины игрового программирования 4
  5. Жемчужины игрового программирования 3
  6. Жемчужины игрового программирования 2
  7. Жемчужины игрового программирования

В каждом из них есть раздел о математических жемчужинах, и там есть много изящных трюков.Эти книги стоят каждого цента.

Есть также жемчужины программирования графических процессоров, так что вы тоже можете их попробовать.

Упражняться:

Если найду еще, отредактирую и добавлю сюда ссылки, но, честно говоря, я нашел эти ссылки примерно за 10 минут использования Google.Самый популярный в мире браузер хранит данные обо всем — и да, «все» также означает матрицы.

Приветствую, приятель.

Я думаю, вам следует потратить несколько дней на создание точечных и перекрестных продуктов с векторами в 3D. Затем изучите связь между тригом и векторами. После этого матрицы станут более понятными для вас.

Курс MIT-OCW по линейной алгебре Гилберта Странга. Невероятные лекции невероятного человека; если ваше понимание матриц основано исключительно на источниках программирования (таких как MATLAB), то курс по линейной алгебре определенно даст вам основы для того, чтобы делать сумасшедшие вещи с помощью матриц.

http://www.ocw.cn /OcwWeb/Mathematics/18-06Spring-2005/VideoLectures/index.htm

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top