Умножение векторов: Умножение вектора на число — урок. Геометрия, 9 класс.

Векторное умножение векторов. Python, Numpy

Вопрос задан

Изменён 1 год 1 месяц назад

Просмотрен 738 раз

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

В коде это у меня выглядит вот так:

def get_normal(translated_vec):
    line1 = translated_vec[1] - translated_vec[0]
    line2 = translated_vec[2] - translated_vec[0]
    normal = np.array([line1[1] * line2[2] - line1[2] * line2[1],
                       line1[2] * line2[0] - line1[0] * line2[2],
                       line1[0] * line2[1] - line1[1] * line2[0]])
    l = np.linalg.norm(normal)
    if l != 0:
        normal /= l
    else:
        normal += 1.
0 return normal

Пример входных данных:

translated_vec = np.array([[ 0.07243389, -0.462265,    4.87585974],
                           [ 0.13487457, -0.3653465,   5.06419032],
                           [ 0.20468741, -0.1275775,   4.95642205]])

Это конечно работает, но работает слишком медленно, я хотел бы как-то это ускорить с помощью numpy, узнал что там есть функция vdot, но она мне не подходит, так как получая на вход два вектора, она выводит не новый вектор, а число. Т. е. мне нужно сделать быструю функцию которая вычисляет это.

  • python
  • python-3.x
  • numpy
  • vector
  • вектор

6

Воспользуйтесь функцией np.cross(a, b, axisa=- 1, axisb=- 1, axisc=- 1, axis=None):

Return the cross product of two (arrays of) vectors.

The cross product of a and b in is a vector perpendicular to both a and b. If a and b are arrays of vectors, the vectors are defined by the last axis of a and b by default, and these axes can have dimensions 2 or 3. Where the dimension of either a or b is 2, the third component of the input vector is assumed to be zero and the cross product calculated accordingly. In cases where both input vectors have dimension 2, the z-component of the cross product is returned.

12

Зарегистрируйтесь или войдите

Регистрация через Google

Регистрация через Facebook

Регистрация через почту

Отправить без регистрации

Почта

Необходима, но никому не показывается

Отправить без регистрации

Почта

Необходима, но никому не показывается

Нажимая на кнопку «Отправить ответ», вы соглашаетесь с нашими пользовательским соглашением, политикой конфиденциальности и политикой о куки

Внешняя алгебра, которую мы заслужили.

Часть 1 — симплексы и границы / Хабр

Мотивация

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

Наше изложение отличается от традиционного, — ориентируемся не столько на точность формулировок, сколько на передачу сути. Осознанно используем отличные от общепринятых обозначения для упрощения формулировок. Это статья для того, чтобы ухватить основную суть. Тогда дальше будет проще.

В первой части определим пространство на основе правил внешнего произведения и сложения объектов. Во второй добавим пространству метрические свойства. В целом пройдем путь от внешнего произведения до представления произвольных графов в виде алгебраического выражения. По дороге познакомимся с основными идеями и инструментами внешней алгебры.

Внешнее произведение

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

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

Выглядит знакомо, да? Но в отличие от привычного произведения чисел внешнее произведение антикоммутативно — проще говоря, меняет знак при перестановке множителей. Вот так:

Это важное свойство, которое является ключевым для внешней алгебры. Из него в частности следует, что внешнее произведение элемента на самого себя может быть только нулем — объектом без знака: .

Какой смысл несет в себе «внешнее произведение». По простому — это ничто иное, как объединение объектов в список. Поэтому, когда элементов много, то их удобно обозначить списком. Такой упорядоченный список выделим квадратными скобками:. При этом надо помнить про наличие знака у списка — при перестановке соседних элементов знак списка меняется на противоположный: . Ну и как следствие — в таком списке не может быть одинаковых элементов.

Список с такими свойствами будем называть симплексом. Симплекс из двух элементов — отрезок, из трех — треугольник, и т. д. (Только надо иметь ввиду, что это топологические отрезки и треугольники. У них нет длин, углов и прочих метрических параметров.). Количество элементов симплекса задает его порядок (грейд). Математики чаще используют понятие мерности. Размерность симплекса на 1 меньше его порядка. То есть отрезок является одномерным.

Симплексы можно умножать друг на друга — это будет эквивалентно объединению двух списков: . Но при наличии в множителях одинаковых элементов результатом объединения будет пустой список — нуль: .

Ну и еще одно полезное правило. При перестановке перемножаемых симплексов местами знак меняется на противоположный, если произведение порядков симплексов нечетное:

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

Обратные элементы

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

Здесь перед коэлементами стоит префикс в виде косой черты /. Если обратный элемент умножается на другой элемент, то результатом будет пустой симплекс — ноль: .

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

Если симплекс умножить на обратный справа, то результат зависит от четности порядка симплекса:

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

Если перемножаемые симплекс и косимплекс содержат элементы, которых нет в другом, то результатом произведения будет ноль: .

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

Линейные комбинации и цепи

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

.

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

Но надо помнить, что умножение здесь внешнее (антикоммутативное). Поэтому некоторые привычные формулы выглядят иначе. Например, внезапно.

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

Линейную комбинацию можно рассматривать как разложение некоего объекта того же порядка по базисным. Например, если у нас есть два объектаи, то можно определить объект как их линейную комбинацию:

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

Коэффициенты разложения элемента по базисным могут быть определены через умножение на коэлементы базиса:

Получается, что внешнее произведение элементов и коэлементов является скалярным (в том смысле, что результат является скаляром). Но между самими элементами скалярное произведение не определено.

Аннулятор и граница

Мы определили симплексы как произведение элементов, определили обратные элементы и обратные симплексы, ввели понятие линейной комбинации симплексов. Пора разобраться с понятием вектор. Часто вектор появляется в учебниках как «черт из табакерки» — то есть явочным порядком. Но постулируя вектор как независимое понятие, мы препятствуем осмыслению его обобщения, создаем искусственный барьер в понимании «реальной картины мира». В нашей алгебре первично понятие объекта (элемента). Вектор — производное понятие, и сейчас мы его «произведем».

Вначале нам понадобится еще одно фундаментальное понятие, которое имеет разные названия, в зависимости от контекста в котором употребляется. Здесь для него используем абстрактный термин — аннулятор, хотя пока и непонятно, чего он там обнуляет. Пусть имеется некое конечное множество элементов, например, . Тогда аннулятором для данного множества является сумма обратных элементов данного множества:

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

Аннулятор позволяет определить граничный оператор над симплексом как внешнее умножение аннулятора на симплекс. Результатом действия является граница. Вот она, граница симплекса:

Границы настолько важны, что не пожалеем для их обозначения отдельных скобок:

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

Граница (симплекса) есть цепь — линейная комбинация симплексов. Порядок границы на 1 меньше порядка образующего ее симплекса. В частности, вектор — это граница 1-порядка, образованная отрезком (симплексом 2-го порядка):

Вектор 2-го порядка называют бивектором, 3-го — тривектором и т.д. Граница произвольного порядка может быть названа мульти- или поливектором.

Действие граничного оператора может быть отменено. Существует элемент, умножая на который границу симплекса, можно восстановить исходный симплекс. Данный элемент называется центроидом множества (или барицентром). Центроид — это среднее суммы элементов:

Здесь круглые скобки — это не обозначение границы, а группировка элементов (обычно смысл скобок понятен из контекста). Проверим действие центроида:

Умножение границы на центроид собирает несколько слагаемых в одно.

Основное свойство границ

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

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

Данная формула раскрывает смысл термина «аннулятор» — при действии на границу аннулятор ее обнуляет. Раскрывая границу как линейную комбинацию симплексов и умножая каждый симплекс на аннулятор, получаем тождества границ:

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

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

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

Произведение границ

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

Если границы имеют один общий элемент, то при умножении они сливаются в одну (компоненту) — это правило слияния границ. Пример слияния двух векторов в 2-границу (бивектор):

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

Итак, порядок границы зависит не только от количества образующих ее элементов , но и от количества ее компонент . Порядок границы равен 2, несмотря на то, что она содержит 4 элемента. Для получения порядка границы надо из количества элементов вычесть количество компонент: .

Кроме того, одна и та же граница может быть образована произведением разных границ меньшего порядка. Например, граница может быть образована тремя разными парами векторов: . То есть произведение границ с общим элементом уничтожает информацию о том, какие именно границы умножались — границы сливаются в одну.

Для тех, кому интересны подробности, откуда все это следует

укажем, что в основе доказательства свойств произведения границ лежит правило Лейбница (цепочки), которое применительно к оператору границы можно записать в следующем виде:

Здесь граничный оператор (умножение на аннулятор слева обозначен как частная производная — это общепринятое обозначение. Используя данное тождество, можно показать, что. Проще всего это сделать раскрытием левой и правой частей по правилу Лейбница.

Немного линейной алгебры…

Пространство элементов, с которым мы тут возимся, принято называть аффинным. Это пространство, в котором есть элементы и их линейные комбинации, но нет метрики.

Насчет метрики следует уточнить. В нашем пространстве не определено скалярное произведение между элементами (и между границами тоже). Поэтому нет возможности определить, например, угол между векторами или сравнить длину (норму) двух произвольных векторов. Но. Из этого не следует, что в аффинном пространстве вообще невозможно ничего сравнивать. Мы вполне можем сравнить длину двух векторов, если они лежат на одной прямой. Мы можем сравнить площади двух бивекторов, если они лежат в одной плоскости и т.д. То есть полноценной метрики в аффинном пространстве нет, но есть полуметрика, которой вполне можно пользоваться. Полуметрика является следствием наличия скалярного произведения между элементами и коэлементами. То есть линейного разложения элементов через другие, базисные.

Рассмотрим пространство, образованное тремя элементами, среди которых выделим центр — общий элемент. Границей пространства будет бивектор базиса. Пусть теперь в данном пространстве есть три элементас известными координатами относительно базисных элементов. Задача состоит в том, чтобы выразить бивекторчерез базисный.

Вначале выпишем координаты элементов. Учтем, что сумма коэффициентов разложения элемента по базисным должна быть равна единице — это следствие того, что граница любого элемента пространства должна быть равна 1: . Такие координаты называются барицентрическими. Тогда для базиса из 3-х элементов две координаты являются независимыми, а третья — выражается через них:

Данная формула может быть представлена как координаты вектора :

Аналогичным образом можно найти координаты векторови. Перемножая векторы, можно выразить координаты бивекторов через базисный бивектор:

Для нахождения искомого бивекторавоспользуемся тождеством границ из предыдущего раздела: . Подставляя в него координаты бивекторов, получаем итоговый ответ:

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

Аффинные координаты и площади

Коэффициент может быть также выражен как детерминант матрицы: . Значения матрицы координатравны произведению элементов и базисных коэлементов (за исключением центра координат):

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

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

… и топологии

Про топологию говорят, что это геометрия без измерений. В том смысле, что конкретные координаты элементов топологам неинтересны. Поэтому коэффициенты топологических цепей всегда равны +-1. Алгебраические выражения границ симплекса можно интерпретировать топологически. В качестве примера приведем разрезание (топологического) квадрата с вершинами на два треугольника. Треугольники в данном случае должны быть ориентированы, то есть иметь знак. Тогда квадрат можно представить как сумму (склейку) треугольников:. Применив к данной цепи граничный оператор, получим цепь из 4-х 2-симплексов — это граница квадрата:

Склейка симплексов

При сложении 2-границ общая сторона треугольников сократилась. В общем случае, можно продолжать склейку треугольников, получая произвольные топологические многогранники. Кажется, что можно любую поверхность представить как сумму треугольников, но на самом деле нет. При покрытии треугольниками поверхности ленты Мёбиуса не удается сократить внутренние границы!

Мы определили границу симплексакак результат действия граничного оператора (умножение аннулятора) на некий симплекс. Повторное взятие границы, как уже отмечалось дает ноль:

Но вообще говоря, возможны и другие цепи (линейные комбинации симплексов), граница которых нулевая. Цепи с нулевой границей называют циклами. Инвариант циклов:

Циклы — это более общее подмножество цепей, чем границы. В общем случае существуют циклы, которые не являются границами какого-либо симплекса. Их называют гомологиями:

Говоря про циклы, снова оговоримся — это топологические циклы. Так же как в топологическом треугольнике нет величины сторон и углов, так и в топологическом цикле нет величины связи между элементами цикла.

Топология — огромный раздел современной математики. Тут мы лишь показали, как порождаются и связываются направления математики через одну простую операцию — внешнее умножение.

Коцепи и дуальность

Для заданного конечного множества независимых элементов существует симплекс предельного порядка, определяемый как произведение всех элементов. Граница данного симплекса называется предельной границей пространства — она имеет максимальный порядок из всех возможных границ на данном множестве. Предельная граница для множества 4-х элементов : .

Предельная граница множества всегда связна (имеет только одну компоненту). Умножение предельной границы на коэлементы понижает ее порядок, но оставляет границу связной: . Умножение предельной границы на сумму коэлементов порождает границы, состоящие из компонент. Например,

Здесь мы видим коцепи 1-го порядка — это линейные комбинации коэлементов. Встречаются также коцепи более высокого порядка. Например, граница из трех компонент может быть получена умножением предельной границы на аннуляторы двух произвольных компонент:

Здесь- предельная граница 6 элементов. Коцепь 2-го порядка:

Видим, что разным коцепям может соответствовать одна и та же граница. Из данных соотношений следует, что границуна конечном множестве элементов можно задать через коцепь. Умножая коцепь на предельную границу, переходим из копространства в обычное:

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

Дуальное преобразование и звездочка Ходжа — это не одно и тоже!

Для тех, кто вообще в курсе про оператор Ходжа. Оператор Ходжа преобразует одни (поли)векторы пространства в другие векторы того же пространства. Дуальное преобразование преобразует коцепи в границы.

Чтобы определить в пространстве оператор Ходжа, надо договориться об общем элементе всех границ. То есть задать начало координат. Такое возможно, поскольку произвольная граница всегда может быть выражена через линейную комбинацию границ с общим элементом (см. граничные тождества). В этом случае становится однозначным дополнение поливектора до предельной границы пространства, которое и называется звездочкой Ходжа.

Можно определить и обратное дуальное преобразование — от границ (цепей) к коцепям. Пусть дана некая граница (в общем случае произвольная цепь). Надо построить дуальную ей коцепь для заданного пространства (симплекса) с предельной границей .

Алгоритм построения может быть таким. Для цепи определяем центроид (средняя сумма элементов, образующих цепь). «Интегрируем» цепь умножением слева на центроид. Переводим полученный «интеграл» из пространства в копространство умножением на косимплекс пространства. Косимплекс пространства однозначно определяется предельной границей. Полученная коцепь и будет искомой:

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

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

умножить-матрица-вектор

умножить-матрица-вектор

Изучение умножения матрицы на вектор с помощью Julia¶

14 августа 2018 г. Джефф Фесслер, Мичиганский университет

05 августа 2020 г. Julia 1.5
23 августа 2023 г. Julia 1.6.2

BenchmarkИнструменты

В [2]:

 # обычная высокоуровневая функция умножения матрицы на вектор.
функция mult0(A::Matrix, x::Vector)
    @boundscheck size(A,2) == длина(x) || бросить("Несоответствие размера(A,x)")
    вернуть А * х
конец;
 

Двойная петля над m,n¶

Это версия для учебника.

В [3]:

 функция mult_mn(A::Matrix, x::Vector)
    (М, N) = размер (А)
    у = аналогичный (х, М)
    для m=1:M
        inprod = zero(eltype(x)) # накопитель
        для n=1:N
            inprod += A[m,n] * x[n]
        конец
        y[m] = входящий продукт
    конец
    вернуть у
конец;
 

В [4]: ​​

 # с @inbounds
функция mult_mn_inbounds(A::Matrix, x::Vector)
    (М, N) = размер (А)
    у = аналогичный (х, М)
    для m=1:M
        inprod = zero(x[1]) # накопитель
        для n=1:N
            @inbounds inprod += A[m,n] * x[n]
        конец
        @inbounds y[m] = inprod
    конец
    вернуть у
конец;
 

Двойной цикл по n,m¶

Мы ожидаем, что этот способ будет быстрее из-за обращения к кешу через m.

В [5]:

 функция mult_nm(A::Matrix, x::Vector)
    (М, N) = размер (А)
    y = нули (eltype (x), M)
    для n=1:N
        для m=1:M
            у[м] += А[м,п] * х[п]
        конец
    конец
    вернуть у
конец;
 

В [6]:

 # с @inbounds
функция mult_nm_inbounds(A::Matrix, x::Vector)
    (М, N) = размер (А)
    y = нули (eltype (x), M)
    для n=1:N
        для m=1:M
            @inbounds y[m] += A[m,n] * x[n]
        конец
    конец
    вернуть у
конец;
 

В [7]:

 # и с @simd
функция mult_nm_inbounds_simd(A::Matrix, x::Vector)
    (М, N) = размер (А)
    y = нули (eltype (x), M)
    для n=1:N
        @simd для m=1:M
            @inbounds y[m] += A[m,n] * x[n]
        конец
    конец
    вернуть у
конец;
 

В [8]:

 # и с @views
функция mult_nm_inbounds_simd_views(A::Matrix, x::Vector)
    (М, N) = размер (А)
    y = нули (eltype (x), M)
    для n=1:N
        @simd для m=1:M
            @inbounds @views y[m] += A[m,n] * x[n]
        конец
    конец
    вернуть у
конец;
 

Версии ряда¶

Петля над m.

В [9]:

 функция mult_row(A::Matrix, x::Vector)
    (М, N) = размер (А)
    у = аналогичный (х, М)
    для m=1:M
        y[m] = транспонировать (A[m,:]) * x
    конец
    вернуть у
конец;
 

В [10]:

 # с @inbounds
функция mult_row_inbounds(A::Matrix, x::Vector)
    (М, N) = размер (А)
    у = аналогичный (х, М)
    для m=1:M
        @inbounds y[m] = транспонировать (A[m,:]) * x
    конец
    вернуть у
конец;
 

В [11]:

 # с @просмотрами
функция mult_row_views(A::Matrix, x::Vector)
    (М, N) = размер (А)
    у = аналогичный (х, М)
    для m=1:M
        @views y [m] = транспонировать (A [m,:]) * x
    конец
    вернуть у
конец;
 

В [12]:

 # с обоими
функция mult_row_inbounds_views(A::Matrix, x::Vector)
    (М, N) = размер (А)
    у = аналогичный (х, М)
    для m=1:M
        @inbounds @views y[m] = транспонировать(A[m,:]) * x
    конец
    вернуть у
конец;
 

Версии Col¶

Цикл по n.

В [13]:

 функция mult_col(A::Matrix, x::Vector)
    (М, N) = размер (А)
    y = нули (eltype (x), M)
    для n=1:N
        у += А[:,п] * х[п]
    конец
    вернуть у
конец;
 

В [14]:

 # с точками (трансляция) для объединения
функция mult_col_dot(A::Matrix, x::Vector)
    (М, N) = размер (А)
    y = нули (eltype (x), M)
    для n=1:N
        y .  10, цифры = 1)
    println("$name : $tim ms $alloc alloc $mem KiB")
конец
 
 mult0 : 0,9 мс 1 выделение 16,1 КиБ
mult_mn : 22,6 мс 1 выделение 16,1 КиБ
mult_mn_inbounds : 22,2 мс 1 выделение 16,1 КиБ
mult_nm : 3,1 мс 1 выделение 16,1 КиБ
mult_nm_inbounds : 1,5 мс 1 выделение 16,1 КиБ
mult_nm_inbounds_simd : 1,5 мс 1 выделение 16,1 КиБ
mult_nm_inbounds_simd_views : 1,5 мс 1 выделение 16,1 КиБ
mult_row : 32,9 мс 2049 выделено 33040,1 КиБ
mult_row_inbounds : 32,9мс 2049 выделить 33040,1 КиБ
mult_row_views : 22,4 мс 1 выделение 16,1 КиБ
mult_row_inbounds_views : 22,5 мс 1 выделение 16,1 КиБ
mult_col : 16,7 мс 6133 распределено 98894,6 КиБ
mult_col_dot : 7,2 мс 2045 выделение 32975,6 КиБ
mult_col_dot_views : 1,5 мс 1 выделение 16,1 КиБ
 

В [17]:

 #=
mult0 : 0,9 мс 1 выделение 16,1 КиБ
mult_mn : 22,5 мс 1 выделение 16,1 КиБ
mult_mn_inbounds : 22,0 мс 1 выделение 16,1 КиБ
mult_nm : 3,1 мс 1 выделение 16,1 КиБ
mult_nm_inbounds : 1,5 мс 1 выделение 16,1 КиБ
mult_nm_inbounds_simd : 1,5 мс 1 выделение 16,1 КиБ
mult_nm_inbounds_simd_views : 1,5 мс 1 выделение 16,1 КиБ
mult_row : 32,8 мс 2049выделить 33040,1 КиБ
mult_row_inbounds : 32,7 мс 2049 выделено 33040,1 КиБ
mult_row_views : 22,4 мс 1 выделение 16,1 КиБ
mult_row_inbounds_views : 22,4 мс 1 выделение 16,1 КиБ
mult_col : 16,0 мс 6133 распределено 98894,6 КиБ
mult_col_dot : 7,0 мс 2045 выделение 32975,6 КиБ
mult_col_dot_views : 1,5 мс 1 выделение 16,1 КиБ
"="
 

Приведенные выше результаты относятся к iMac 2017 года с четырехъядерным процессором Intel Core i7 с тактовой частотой 4,2 ГГц с macOS Mojave 10. 14.6 и Julia 1.6.2. Как и ожидалось, просто A*x самый быстрый, но можно приблизиться к этому, используя правильный порядок двойного цикла с @inbounds или используя «точки» и @views для объединения. Без @views векторные версии имеют огромные накладные расходы памяти!

Умножение массива/вектора для одноэлементных массивов — Новое в Julia

willcclarke

1

Привет, я давний пользователь Matlab, только начинаю погружаться в мир Джулии, так что простите меня, если мой вопрос наивен.

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

Допустим, у меня есть следующая функция

 function double(A::Array{<:Real}, B::Array{<:Real})
    С = А*В
    2*С
конец
 

которые я оцениваю следующим образом

 julia> A = [1 2;3 4]
Массив 2×2{Int64,2}:
 1 2
 3 4
юлия> В = [5;6]
2-элементный массив{Int64,1}:
 5
 6
юлия>
двойной(А,В) 2-элементный массив{Int64,1}: 34 78

Все работает как положено. А что, если A и B определены, как показано ниже:

 julia> A = [1;2]
2-элементный массив{Int64,1}:
 1
 2
юлия> В = [3]
1-элементный массив {Int64,1}:
 3
юлия> двойной(А,В)
ОШИБКА: MethodError: метод не соответствует *(::Array{Int64,1}, ::Array{Int64,1})
 

Таким образом, несмотря на то, что это умножение математически корректно, оно не дает успешных результатов. Я решил эту проблему, расширив оператор *, используя следующую функцию

 function Base.:*(A::Array{<:Number,1}, B::Array{<:Number,1})
    если длина (А) == 1
        А[1]*Б
    иначе длина (B) == 1
        А*Б[1]
    еще
        error("Размеры массива не подходят для умножения. ")
    конец
конец
 

Это работает нормально, однако мне кажется, что это не очень хорошая практика. Я надеялся, что кто-нибудь может дать совет о более «юлианском» способе сделать это, или если это действительно подходящий подход.

Заранее спасибо, Уилл.

Оскар_Смит

2

Итак, проблема в том, что вы перепутали * и .* первое - умножение матриц. Второе - это векторизованное умножение, которое вам нужно. В общем, чтобы применить операцию поэлементно, используйте ф. (точка ставится перед инфиксными функциями).

УиллкКларк

3

Оскар, спасибо за быстрый ответ.

Умножение матриц — это действительно то, что мне нужно, а не поэлементное умножение. В частности, я хочу оценить умножение матриц A и B, где A имеет размеры n x m, а B имеет размеры m x 1 (или, если уж на то пошло, m x p). И n, и m могут быть любыми положительными целыми числами, включая 1,9.0007

Энрике_Беккер

4

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

Вы уверены, что не хотите:

 > A = [1;2]; В = [3];
> А * Б'
Массив 2×1{Int64,2}:
 3
 6
 

Другими словами, эта операция на самом деле не определена для векторов ( Массив{T, 1} ), она определена для матриц ( Массив{T, 2} ). Вы должны использовать правильный тип.

Лэнгуен-вн

5

Привет,
Добро пожаловать в сообщество Julia! Хотя Джулия может показаться пользователям MatLab очень знакомой, между ними есть некоторые тонкие отличия. Обратите внимание, что во втором примере и A, и B являются векторами-столбцами (массив только с одним измерением), и поэтому метод умножения не определен, поскольку неясно, хотите ли вы внутренний или внешний продукт.
Чтобы добиться того, что вы хотите, вы можете сделать A * transpose(B) или A * B' (последнее на самом деле является присоединением к B , но дает тот же результат). Это математически последовательно, так как то, что вы действительно хотите, это умножение матриц, а транспонировать (B) или B' можно рассматривать как матрицы 1 на 1.
Однако рекомендация Оскара по широковещательному умножению, пожалуй, самый удобный способ.

Оскар_Смит

6

Нет, мое предположение было неверным, если обобщенным желаемым поведением является умножение матриц.

1 Нравится

УиллКларк

7

А как насчет другого случая в моем исходном посте, когда

 julia> A = [1 2;3 4];B = [5;6];
юлия> А*В'
ОШИБКА: DimensionMismatch («матрица A имеет размеры (2,2), матрица B имеет размеры (1,2)»)
 

Неудивительно, что это выдает ошибку, поскольку размеры не совпадают. Получается, что этот подход вообще не годится для A с размерами n x m и B с размерами m x 1?

Энрике_Беккер

8

Обратите внимание на типы:

 > A = [1 2; 3 4]
Массив 2×2{Int64,2}:
 1 2
 3 4
> В = [5;6]
2-элементный массив{Int64,1}:
 5
 6
> А = [1;2]
2-элементный массив{Int64,1}:
 1
 2
> В = [3]
1-элементный массив {Int64,1}:
 3
 

Другими словами, в первом случае умножение работает, потому что две матрицы Array{T, 2} правильных размеров. Во втором случае они не являются матрицами правильных размеров, чтобы они были матрицами правильных размеров, вам необходимо правильно объявить их с самого начала или использовать оператор ' , который я использовал для получения второго операнда ( B ) с правильный тип.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *