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

Этот вопрос довольно старый, но он все еще высоко ценится в Google в 2019 году, а также некоторые более ранние ответы устарели, поэтому я подумал, что поделюсь возможным решением.

В модели вводятся некоторые области с тестом на наличие переданного параметра:

class Post
    scope :where_author_ids, ->(ids){ where(author_id: ids.split(‘,’)) if ids }
    scope :where_topic_ids,  ->(ids){ where(topic_id:  ids.split(‘,’)) if ids }

Затем в контроллере вы можете просто установить столько фильтров, сколько пожелаете, например:

def list
    @posts = Post.where_author_ids(params[:author_ids])
                 .where_topic_ids(params[:topic_ids])                                  
                 .where_other_condition_ids(params[:other_condition_ids])
                 .order(:created_at)

Параметр может быть одним значением или разделенным запятыми списком значений, оба работают нормально.

Если param не существует, он просто пропускает предложение where и не фильтрует его по определенным критериям. Если параметр существует, но его значение является пустой строкой, он будет «отфильтровывать» все.

Конечно, это решение не подходит для любых обстоятельств. Если у вас есть страница просмотра с несколькими фильтрами, но при первом открытии вы хотите показать все свои данные, а не данные, пока не нажмете кнопку «Отправить» или аналогичную (как это сделал бы контроллер), вам придется слегка подправить ее. ,

Я попробовал SQL-инъекцию, и rails, кажется, хорошо справляется с обеспечением безопасности, насколько я могу видеть.

23
задан gdrt 29 July 2017 в 02:33
поделиться

10 ответов

Исходный ответ: Я не уверен, понравится ли вам, как математические курсы обычно вводят матрицы. Как программист, вы, возможно, будете счастливее взять любую приличную книгу по 3D-графике. У него обязательно должны быть очень конкретные матрицы 3x3. Также найдите те, которые научат вас проективным преобразованиям (проективная геометрия - очень красивая область низкоразмерной геометрии и ее легко программировать).

Мини-курс матричной математики на Python 3

Содержание:

  1. Матрицы [Вектор, __add__, отражать_y, вращать, расширять, преобразовать]
  2. Матрицы: перегружены [Матрица, __add__, __str__, __mul__, zero, det , inv, __pow __]
  3. Бонус: Комплексные числа
  4. Матрицы: (R) эволюция . Он уже в разработке (там ' (резюме в конце)

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

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

  • Это пост длинный. Вы можете подумать о том, чтобы распечатать это и продвигаться медленно, например, одну часть в день.
  • Код необходим. Это курс для программистов. Упражнения тоже необходимы.
  • Вам следует взглянуть на сопутствующий код , который содержит весь этот код и многое другое.
  • Это «2 по цене 1» special: вы также можете изучить Python 3 здесь. И комплексные числа.
  • Я высоко ценю любую попытку прочитать это (могу ли я официально претендовать на самый длинный пост в истории?), Поэтому не стесняйтесь комментировать, если вы чего-то не понимаете (а также, если вы понимаете).

1. Матрицы

Векторы

Перед матрицами идут векторы. Вы наверняка знаете, как работать с двумерными и трехмерными векторами:

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 (...) , используя описанные ниже операции? А как насчет reflection_x ?

Теперь вы можете задаться вопросом, почему я пропустил reflection_y . Ну, это потому, что я хочу, чтобы вы на мгновение остановились и написали свою собственную версию. Хорошо, вот мой:

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

Видите ли, если вы посмотрите, как эта функция вычисляет, на самом деле это довольно тривиально. Но вдруг произошло удивительное: Мне удалось написать преобразование, используя только существующие преобразования flip и Reflection_x . Мне все равно, Reflection_y можно определить в производном классе без доступа к x и y , и это все равно будет работать!

Математики назвали бы это функции операторы . Они сказали бы, что reflection_y - это оператор, полученный композицией операторов flip и reflection_x , что является обозначается отражать_y = перевернуть ○ отражать_x (вы должны увидеть маленький кружок, символ Юникода 25CB ).

  • Примечание: Я буду свободно использовать = , чтобы обозначить, что две операции производят одинаковый результат, как в предыдущем абзаце. Это «математическое = », которое не может быть выражено как программа .

Так что, если я сделаю

print(v.reflect_y())

, я получу результат (- 5, 3 ) . Иди и представь это!

  • Вопрос: Рассмотрим композицию Reflection_y ◦ Reflection_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 ?

Dilations

Эти вращения, безусловно, полезны, но это не все, что вам нужно даже для 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 (?,?) = Отражать_x .

Я буду использовать эта функция dilate демонстрирует то, что математики называют коммутативностью : то есть для каждого значения параметров a , b , c , d вы можете быть уверены, что

dilate(a, b) ◦ dilate(c, d) = dilate(c, d) ◦ dilate(a, b)
  • Exercise: Докажите это. Кроме того, верно ли, что для всех возможных значений параметров будут выполняться те, которые ниже?

    • 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 , reflection_x , * , rotate (angle) , dilate (x, y)

, из которого можно сделать действительно сумасшедшие вещи вроде

  • flip ◦ rotate (angle) ◦ dilate (x, y) ◦ rotate (angle_2) ◦ Reflection_y + Reflection_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)

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

  • Пример: Определить, какие значения у '?' предназначены для __ 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) . Обратите внимание, что если вы примените преобразование с Не бойся! Волшебным образом каждое выражение в приведенной выше форме может быть упрощено до

    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)

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

  • Пример: Определить, какие значения у '?' предназначены для __ 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) . Обратите внимание, что если вы примените преобразование с Не бойся! Волшебным образом каждое выражение в приведенной выше форме может быть упрощено до

    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)

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

  • Пример: Определить, какие значения у '?' предназначены для __ 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) . Обратите внимание, что если вы примените преобразование с Определите, каковы значения "?" предназначены для __ 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) . Обратите внимание, что если вы примените преобразование с Определите, каковы значения "?" предназначены для __ 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) . Обратите внимание, что если вы примените преобразование с и применить его к вектору x . Вот пример:

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

    , который печатает (5, 3) (-3, 5) (-3, 5) . Обратите внимание, что если вы примените преобразование с и применить его к вектору x . Вот пример:

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

    , который печатает (5, 3) (-3, 5) (-3, 5) . Обратите внимание, что если вы примените преобразование с любая матрица в начало координат, вы все равно получите исходную точку:

    origin = Vector(0, 0)
    print(origin.transform(rotation_90_matrix))
    
    • Упражнение: какие кортежи m описывают переворот , dilate (x, y) , rotate (angle) ?

    Когда мы расстаемся с классом Vector , вот упражнение для тех, кто хочет проверить как свои знания векторной математики, так и навыки Python:

    • Последняя битва: Добавьте к классу 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 , но чтобы увидеть результаты, мы должны выяснить, как напечатать матрицу. числа и распечатайте их в полях фиксированной длины.

    Теперь вы можете написать матрицу для вращения:

    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) и заполните вопросительные знаки. Тест с

       из math import pi
      печать (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 , который, если вы откроете круглые скобки, выглядит подозрительно похожим to Matrix .__ вызов __ с использованием нового кортежа 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)))
      печать (R (3))
      
    • Математическое упражнение: Докажите, что R (a) .compose (R (b)) всегда совпадает с R (a + b) .

    Теперь позвольте мне сказать правду: эта функция compose на самом деле представляет собой то, как математики решили умножить матриц. Это имеет смысл в виде записи: A * B - это матрица, описывающая оператор A ○ B , и, как мы увидим далее, есть более глубокие причины называть это «умножением» как хорошо.

    Чтобы начать использовать умножение в Python, все, что нам нужно сделать, это упорядочить его так в Matrix class:

        class Matrix:
    
              ...
    
            __mul__ = compose
    
    • Упражнение: Вычислить (R (pi / 2) + R (pi)) * (R (-pi / 2) + R (pi)) . Попробуйте сначала найти ответ на листе бумаги.

    Правила для + и *

    Давайте придумаем хорошее название для матрицы, которая соответствует расширению ( а, б) оператор . Теперь все в порядке с 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 .

    Это несколько странно, поскольку умножение чисел всегда коммутативно, и возникает вопрос, может ли составлять действительно заслуживает того, чтобы называться __ 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 + ноль = A
    2. A * ноль = ноль
    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) подходит. Теперь это нельзя выразить как лямбда v: A (v) , но можно записать в виде лямбда 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 . Давайте решим систему, как преподают в (некоторых) средних школах: умножьте первое уравнение на Am [3] , второе на -Am 1 и сложите (если сомневаетесь, сделайте это на лист бумаги), чтобы найти vx .

    Если вы действительно попробовали, у вас должно было быть A.det () * vx = (Am [3]) * bx + ( -Am [1]) * на , что предполагает, что вы всегда можете получить 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: ...
    
    • Exercise: Завершите метод. Докажите, что обратной матрицы не существует, если self.det () == 0 . Напишите метод разделения матриц и протестируйте его. Используйте обратную матрицу для решения уравнения A (v) = x_axis ( A было определено выше).

    Полномочия

    Основное свойство обратной матрицы состоит в том, что ] A * A.inv () всегда равно one

    • Упражнение: проверьте это сами. Объясните, почему это должно быть так, исходя из определения обратной матрицы.

    Вот почему математики обозначают A.inv () как A -1 . Как насчет того, чтобы написать s почему математики обозначают A.inv () как A -1 . Как насчет того, чтобы написать s почему математики обозначают A.inv () как A -1 . Как насчет того, чтобы написать удобная функция для использования обозначения A ** n для A n ? Обратите внимание, что наивный для i в диапазоне (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) . Это единственно возможный ответ? Найдите пример матрицы, у которой не квадратный корень.

    Бонус: Комплексные числа

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

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

    Я упустил из виду вопрос о том, как напечатать результат операции вида 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. Матрицы: (R) эволюция

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

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

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

    Думаю, если бы вы могли терпеть меня до этого момента, вас могло бы заинтересовать это продолжение, поэтому я хотел бы услышать, следует ли мне продолжить это (и где,

    44
    ответ дан 29 November 2019 в 01:01
    поделиться

    MIT имеет много материалов своих курсов по математике в Интернете по адресу http : //ocw.mit.edu/OcwWeb/Mat Mathematics/ . Когда вы освоите основы, у них также будут онлайн-заметки по физике.

    8
    ответ дан 29 November 2019 в 01:01
    поделиться
    6
    ответ дан 29 November 2019 в 01:01
    поделиться

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

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

    2
    ответ дан 29 November 2019 в 01:01
    поделиться

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

    1
    ответ дан 29 November 2019 в 01:01
    поделиться

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

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

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

    2
    ответ дан 29 November 2019 в 01:01
    поделиться

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

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

    1
    ответ дан 29 November 2019 в 01:01
    поделиться

    Those are the information that I found. Some of them might be valuable to You:

    Theory:

    (Searching for "Matrices" at Google books gives You lots of lecutures, some of which are directly connected with transformations - this is one of the first results, but I cheer You to check more.)

    I also encourage (I don't know if this is the right word, I am just learning English) You, to look for this kind of information in one of those books (though they are not free, but You can find large parts of older ones on Google Books):

    1. Game programming gems 7
    2. Game programming gems 6
    3. Game programming gems 5
    4. Game programming gems 4
    5. Game programming gems 3
    6. Game programming gems 2
    7. Game programming gems

    Each of those has section about math gems - and there are lots of neat tricks there. Those books are worth every cent.

    There are also GPU Programming gems, so You might try them too.

    Practice:

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

    Ура, приятель.

    1
    ответ дан 29 November 2019 в 01:01
    поделиться

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

    1
    ответ дан 29 November 2019 в 01:01
    поделиться

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

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

    1
    ответ дан 29 November 2019 в 01:01
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: