Русский
Русский
English
Статистика
Реклама

Вектор

Векторные пространства

13.08.2020 12:11:08 | Автор: admin

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

Операция деления как раз одна из самых дорогих операций. Дело в том, что в алгебраических полях, а соответственно и в группах операция деления вообще отсутствует и выход из положения (когда не делить нельзя) состоит в том, что операцию деления заменяют умножением, но умножают не на саму координату, а на обращенное ее значение. Из этого следует, что предварительно надо привлекать расширенный алгоритм Евклида НОД и кое что еще. Одним словом, не все так просто как изображают авторы большинства публикаций о ЕСС. Почти все, что по этой теме опубликовано и не только в Интернете мне знакомо. Мало того, что авторы не компетентны и занимаются профанацией, оценщики этих публикаций плюсуют авторов в комментариях, т. е. не видят ни пробелов, ни явных ошибок. Про нормальную же статью пишут, что она уже 100500-я и от нее нулевой эффект. Так все пока на Хабре устроено, анализ публикаций делается огромный, но не качества содержания. Здесь возразить нечего реклама двигатель бизнеса.


Линейное векторное пространство


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

Пусть r<3> = <r1, r2, r3> вектор трехмерного пространства, задает положение одной частицы (точки) относительно начала координат. Если рассматривать N элементов, то описание их положения требует задания 3N координат, которые можно рассматривать как координаты некоторого вектора в 3N-мерном пространстве. Если рассматривать непрерывные функции и их совокупности, то приходим к пространствам, размерность которых равна бесконечности. На практике часто ограничиваются использованием лишь подпространства такого бесконечномерного пространства функции координат, обладающего конечным числом измерений.

Пример 1. Ряд Фурье пример использования пространства функций. Рассмотрим разложение произвольной функции в ряд Фурье



Его можно трактовать как разложение вектора f(x) по бесконечному набору ортогональных базисных векторов sinпх
Это пример абстрагирования и распространения понятия вектора на бесконечное число измерений. Действительно, известно, что при -x

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

Набор векторов r1, r2, будем называть линейным векторным пространством L, если сумма любых двух его элементов тоже находится в этом наборе и если результат умножения элемента на число С также входит в этот набор. Оговоримся сразу, что значения числа С могут быть выбраны из вполне определенного числового множества Fр поля вычетов по модулю простого числа р, которое считается присоединенным к L.
Пример 2. Набор из 8 векторов, составленных из n =5 -разрядных двоичных чисел
r0 = 00000, r1 = 10101, r2 = 01111, r3 = 11010, r4 = 00101, r5 = 10110, r6 = 01001, r7 = 11100 образует векторное пространство L, если числа С {0,1}. Этот небольшой пример позволяет убедиться в проявлении свойств векторного пространства, включенных в его определение.
Суммирование этих векторов выполняется поразрядно по модулю два, т. е. без переноса единиц в старший разряд. Отметим, что если все С действительные (в общем случае С принадлежат полю комплексных чисел), то векторное пространство называют действительным.
Формально аксиомы векторного пространства и записываются так:
r1 + r2 = r2 + r1 = r3; r1, r2, r3 L коммутативность сложения и замкнутость;
(r1 + r2) + r3 = r1 + (r2 + r3) = r1 + r2 + r3 ассоциативность сложения;
ri + r0 = r0 + ri = ri; i, ri, r0 Lсуществование нейтрального элемента;
ri +(- ri) = r0, для i существует противоположный вектор (-ri) L;
1 ri = ri 1 = ri существование единицы для умножения;
(ri) = ()ri; , , 1, 0 элементы числового поля F, ri L; умножение на скаляры ассоциативно; результат умножения принадлежит L;
( + ) ri = ri + ri; для i, ri L, , скаляры;
а (ri + rj) = ari + arj для всех а, ri, rj L;
a0 = 0, 0ri = 0; (-1) ri = ri.

Размерность и базис векторного пространства


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

Линейная независимость векторов
Набор векторов r1, r2, r3 rр из L называют линейно независимым, если для них соотношение

выполняется только при условии одновременного равенства $inline$с_1=с_2==с_р=0$inline$.
Все $inline$с_k$inline$, k = 1(1)p, принадлежат числовому полю вычетов по модулю два
F = {0, 1}.
Если в некотором векторном пространстве L можно подобрать набор из р векторов, для которых соотношение $inline$c_1 r_1+c_2 r_2+...+c_p r_p=0 $inline$ выполняется, при условии, что не все $inline$с_k = 0$inline$ одновременно, т.е. в поле вычетов оказалось возможным выбрать набор $inline$с_k$inline$, k =1(1)р, среди которых есть ненулевые, то такие векторы $inline$r_i$inline$ называются линейно зависимыми.

Пример 3. На плоскости два вектора $inline$е_1$inline$ = <0, 1>T и $inline$е_2$inline$ = <1, 0>T являются линейно независимыми, так как в соотношении (T-транспонирование)

невозможно подобрать никакой пары чисел $inline$с_1, с_2$inline$ коэффициентов не равных нулю одновременно, чтобы соотношение было выполнено.
Три вектора $inline$е_1$inline$ = <0, 1>T, $inline$е_2$inline$ = <1, 0>T, $inline$е_3$inline$ = <1, 1>T образуют систему линейно зависимых векторов, так как в соотношении

равенство может быть обеспечено выбором коэффициентов $inline$с_1 = с_2 = 1, с_3 = 1$inline$, не равных нулю одновременно. Более того, вектор $inline$ e_3 = е_1 + е_2 $inline$ является функцией $inline$ е_1$inline$ и $inline$ е_2 $inline$ (их суммой), что указывает на зависимость $inline$ e_3 $inline$ от $inline$е_1$inline$ и $inline$е_2 $inline$. Доказательство общего случая состоит в следующем.

Пусть хотя бы одно из значений $inline$с_k$inline$, k = 1(1)р, например, $inline$с_р 0$inline$, а соотношение выполнено. Это означает, что векторы $inline$r_k$inline$, k = 1(1)р, линейно зависимы

Выделим явным образом из суммы вектор rр

Говорят, что вектор rр является л и н е й н о й комбинацией векторов $inline$r_1, r_2 r_р-1$inline$ или rр через остальные векторы выражается линейным образом, т.е. rр линейно зависит от остальных. Он является их функцией.

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

Зависимость/независимость совокупности {$inline${e_1, e_2, e_3, ..., e_n}$inline$} векторов часто определяют, вычисляя определитель матрицы Грама (ее строки скалярные произведения наших векторов). Если определитель равен нулю, среди векторов имеются зависимые, если определитель отличен от нуля векторы в матрице независимы.

Определителем Грама (грамианом) системы векторов

$$display$$ {\displaystyle \mathbf {e} _{1},\;\mathbf {e} _{2},\;\ldots ,\mathbf {e} _{n}}\mathbf{e}_1,\;\mathbf{e}_2,\;\ldots,\mathbf{e}_n$$display$$

в евклидовом пространстве называется определитель матрицы Грама этой системы:

$$display$${\displaystyle {\begin{vmatrix}\langle e_{1},\;e_{1}\rangle &\langle e_{1},\;e_{2}\rangle &\ldots &\langle e_{1},\;e_{n}\rangle \\\langle e_{2},\;e_{1}\rangle &\langle e_{2},\;e_{2}\rangle &\ldots &\langle e_{2},\;e_{n}\rangle \\\ldots &\ldots &\ldots &\ldots \\\langle e_{n},\;e_{1}\rangle &\langle e_{n},\;e_{2}\rangle &\ldots &\langle e_{n},\;e_{n}\rangle \\\end{vmatrix}},}\begin{vmatrix} \langle e_1,\;e_1\rangle & \langle e_1,\;e_2\rangle & \ldots & \langle e_1,\;e_n\rangle \\ \langle e_2,\;e_1\rangle & \langle e_2,\;e_2\rangle & \ldots & \langle e_2,\;e_n\rangle \\ \ldots & \ldots & \ldots & \ldots \\ \langle e_n,\;e_1\rangle & \langle e_n,\;e_2\rangle & \ldots & \langle e_n,\;e_n\rangle \\ \end{vmatrix},$$display$$



где $inline${\displaystyle \langle e_{i},\;e_{j}\rangle }\langle e_i,\;e_j\rangle{\displaystyle \langle e_{i},\;e_{j}\rangle }\langle e_i,\;e_j\rangle$inline$ скалярное произведение векторов
$inline${\displaystyle \mathbf {e} _{i}}\mathbf{e}_i$inline$ и $inline${\displaystyle \mathbf {e} _{j}}\mathbf{e}_j$inline$.

Размерность и базис векторного пространства
Размерность s = d (L) пространства L определяется как наибольшее число векторов в L, образующих линейно независимый набор. Размерность это не число векторов в L, которое может быть бесконечным и не число компонентов вектора.
Пространства, имеющие конечную размерность s , называются конечномерными, если
s = , бесконечномерными.
Ответом на вопрос о минимальном числе и составе векторов, которые обеспечивают порождение всех векторов линейного векторного пространства является следующее утверждение.
Любой набор s линейно независимых векторов в пространстве L образует его б а з и с. Это следует из того, что любой вектор $inline$r_k$inline$ линейного s-мерного векторного пространства L может быть представлен единственным способом в виде линейной комбинации векторов базиса.
Зафиксируем и обозначим символом $inline$е_i $inline$, i = 1(1)s, один из наборов, образующих базис пространства L. Тогда

Числа rki, i = 1(1)s называются координатами вектора $inline$r_k $inline$ в базисе $inline$е_i $inline$, i = 1(1)s, причем rki = ($inline$е_i $inline$, $inline$r_k $inline$).
Покажем единственность представления $inline$r_k $inline$. Очевидно, что набор $inline$e_1,e_2,...,e_s$inline$, $inline$ r_k $inline$ является зависимым, так как $inline$е_i$inline$, i = 1(1)s базис. Другими словами, существуют такие $inline$с_1, с_2... с_s, c_k$inline$ не равные одновременно нулю, что $inline$ c_1e_1 + c_2e_2 + ...+ c_se_s + c_kr_k = 0$inline$.
При этом пусть $inline$c_k 0$inline$, ибо если $inline$ c_k = 0 $inline$, то хоть одно из $inline$с_1, с_2 , ... , с_s$inline$, было бы отлично от нуля и тогда векторы $inline$ e_i $inline$, i = 1(1)s, были бы линейно зависимы, что невозможно, так как это базис. Следовательно,
Полагая
, будем иметь
Используя прием доказательства от противного, допустим, что записанное представление $inline$r_k $inline$ не единственное в этом базисе и существует другое

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

Очевидно, что правая и левая части равны, но левая представляет разность вектора с самим собой, т. е. равна нулю. Следовательно, и правая часть равна нулю. Векторы $inline$ е_i $inline$, i = 1(1)s линейно независимы, поэтому все коэффициенты при них могут быть только нулевыми. Отсюда получаем, что
а это возможно только при


Выбор базиса. Ортонормированность


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

Необходимость рассмотрения ортонормированных базисов вызвана потребностями использования быстрых преобразований как одно , так и многомерных функций. Задачи такой обработки возникают при исследовании кодов, кодирующих информационные сообщения в сетях связи различного назначения, при исследовании изображений, получаемых
посредством автоматических и автоматизированных устройств, в ряде других областей, использующих цифровые представления информации.
Определение. Совокупность n линейно независимых векторов n-мерного векторного
пространства V называется его базисом.

Теорема. Каждый вектор х линейного n-мерного векторного пространства V можно представить, притом единственным образом, в виде линейной комбинации векторов базиса. Векторное пространство V над полем F обладает следующими свойствами:
0х = 0 (0 в левой части равенства нейтральный элемент аддитивной группы поля F; 0 в правой части равенства элемент пространства V, являющийся нейтральным единичным элементом аддитивной группы V, называемый нулевым вектором);
( 1)х = х; 1 F; x V; x V;
Если х = 0V, то при х 0 всегда = 0.
Пусть Vn(F) множество всех последовательностей (х1, х2, , хn) длины n с компонентами из поля F, т.е. Vn(F) ={x, таких, что х = (х1, х2, , хn), хi F;
i =1(1)n }.

Сложение и умножение на скаляр определяются следующим образом:
x + y =(x1 + y1, x2 + y2, , xn + yn);
х = (х1, х2,, хn), где у = (у1, у2,, уn),
тогда Vn(F) является векторным пространством над полем F.

Пример 4. В векторном пространстве rо = 00000, r1 = 10101, r2 = 11010, r3 = 10101 над полем F2 = {0,1} определить его размерность и базис.
Решение. Сформируем таблицу сложения векторов линейного векторного пространства

В этом векторном пространстве V= {rо,r1,r2,r3} каждый вектор в качестве противоположного имеет самого себя. Любые два вектора, исключая rо, являются линейно независимыми, в чем легко убедиться
c1r1 + c2r2 = 0; c1r1 + c3r3 = 0; c2r2 + c3r3 = 0;

Каждое из трех соотношений справедливо только при одновременных нулевых значениях пар коэффициентов сi, сj {0,1}.

При одновременном рассмотрении трех ненулевых векторов один из них всегда является суммой двух других или равен самому себе, а r1+r2+r3=rо.
Таким образом, размерность рассматриваемого линейного векторного пространства равна двум s = 2, d(L) = s = 2, хотя каждый из векторов имеет пять компонентов. Базисом пространства является набор (r1, r2). Можно в качестве базиса использовать пару (r1, r3).

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

Если размерность векторного пространства равна k и равна числу строк матрицы G, рангу матрицы G, то очевидно, существует k коэффициентов с q различными значениями для порождения всех возможных линейных комбинаций строк матрицы. При этом векторное пространство L содержит qk векторов.

Множество всех векторов из pn с операциями сложения векторов и умножения вектора на скаляр из p есть линейное векторное пространство.
Определение. Подмножество W векторного пространства V, удовлетворяющее условиям:
Если w1, w2 W, то w1+ w2 W,
Для любых F и w W элемент w W,
само является векторным пространством над полем F и называется подпространством векторного пространства V.
Пусть V есть векторное пространство над полем F и множество W V. Множество W есть подпространство пространства V, если W по отношению к линейным операциям, определенным в V, есть линейное векторное пространство.

Таблица. Характеристики векторных пространств


Компактность матричного представления векторного пространства очевидна. Например, задание L векторов двоичных 50-разрядных чисел, среди которых 30 векторов образуют базис векторного пространства, требует формирования матрицы G[30,50], а описываемое количество векторов превышает 109, что в поэлементной записи представляется неразумным.

Все базисы любого пространства L разбиваются подгруппой Р невырожденных матриц с det G > 0 на два класса. Один из них (произвольно) называют классом с положительно ориентированными базисами (правыми), другой класс содержит левые базисы.
В этом случае говорят, что в пространстве задана ориентация. После этого любой базис представляет собой упорядоченный набор векторов.
Если нумерацию двух векторов изменить в правом базисе, то базис станет левым. Это связано с тем, что в матрице G поменяются местами две строки, следовательно, определитель detG изменит знак.

Норма и скалярное произведение векторов


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

Действительное или комплексное векторное пространство L называется нормированным векторным пространством, если каждый вектор r в нем может быть сопоставлен действительному числу || r || модулю вектора, норме. Единичный вектор это вектор, норма которого равна единице. Нулевой вектор имеет компонентами нули.
Определение. Векторное пространство называется унитарным, если в нем определена бинарная операция, ставящая каждой паре ri, rj векторов из L в соответствие скаляр. В круглых скобках (ri, rj) записывается (обозначается) скалярное или внутреннее произведение ri и rj, причем
1. (ri, rj) = ri rj;
2. (ri, rj) = (ri rj)*, где * указывает на комплексное сопряжение или эрмитову симметрию;
3. (сri, rj) = с(ri rj) ассоциативный закон;
4. (ri + rj, rk) = (ri rk)+ (rj rk) дистрибутивный закон;
5. (ri, rk) 0 и из (ri, rj ) = 0 следует ri = 0.

Определение. Положительное значение квадратного корня называют нормой (или длиной, модулем) вектора ri. Если = 1, то вектор ri называют нормированным.

Два вектора ri, rj унитарного векторного пространства L взаимно ортогональны, если их скалярное произведение равно нулю, т.е. (ri, rj) = 0.
При s = 3 в линейном векторном пространстве в качестве базиса удобно выбирать три взаимно перпендикулярных вектора. Такой выбор существенно упрощает ряд зависимостей и вычислений. Этот же принцип ортогональности используется при выборе базиса в пространствах и других размерностей s > 3. Использование введенной операции скалярного произведения векторов обеспечивает возможность такого выбора.

Еще большие преимущества достигаются при выборе в качестве базиса векторного пространства ортогональных нормированных векторов ортонормированного базиса. Если не оговорено специально, то далее всегда будем считать, что базис еi, i = 1(1)s выбран именно таким образом, т.е.
, где ij символ Кронекера (1823 1891).

В унитарных векторных пространствах такой выбор всегда реализуем. Покажем реализуемость такого выбора.
Определение. Пусть S = {v1, v2,, vn} есть конечное подмножество векторного пространства V над полем F.
Линейная комбинация векторов из S есть выражение вида а1v1 + а2v2 ++ аnvn, где каждое аi F.
Оболочка для множества S (обозначение {S}) есть множество всех линейных комбинаций векторов из S. Оболочка для S есть подпространство пространства V.

Если U есть пространство в V, то U натянуто на S (S стягивает U), если {S}=U.
Множество векторов S линейно зависимо над F, если в F существуют скаляры а1, а2,, аn, не все нули, для которых а1v1+ а2v2 ++ аnvn = 0. Если таких скаляров не существует, то множество векторов S линейно независимо над F.
Если векторное пространство V натянуто на линейно независимую систему векторов S (или система S стягивает пространство V), то система S называется базисом для V.

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


Пусть в пространстве V имеется не ортонормированный базис i, i = 1(1)s. Обозначим норму каждого вектора базиса символом
Известно следующее утверждение [11]. Если i, i = 1(1)s произвольная конечная или счетная система линейно независимых векторов в унитарном векторном пространстве, то существует ортонормированная система i, i = 1(1)s, порождающая то же самое линейное пространство (многообразие).

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

В развернутом виде алгоритм ортогонализации и нормирования базиса содержит следующие условия:

Делим вектор 1, на его норму; получим нормированный вектор i= 1/(|| 1 ||);
Формируем V2 = 2 ( 1, 2)e 1 и нормируем его, получим е 2. Ясно, что тогда
(е1, е2) ~ (е1, е2) (е1, 2)( е1, е1) = 0;
Построив V3 = 3 (e1, 3)e1 (e2, 3) e2 и нормируя его, получим е3.

Для него имеем сразу же (е1, е3) = (е2, е3) = 0.
Продолжая такой процесс, получим ортонормированный набор i, i = 1(1)s. Этот набор содержит линейно независимые векторы, поскольку все они взаимно ортогональны.
Убедимся в этом. Пусть выполняется соотношение

Если набор i, i = 1(1)s зависимый, то хотя бы один сj коэффициент не равен нулю сj 0.

Умножив обе части соотношения на еj, получаем
(ej, c1e1 ) + (ej, c2e2 )+ ...+ ( ej, cjej ) ++ ( ej, csrs ) = 0.
Каждое слагаемое в сумме равно нулю как скалярное произведение ортогональных векторов, кроме (ej ,cjej), которое равно нулю по условию. Но в этом слагаемом
(ej, ej) = 1 0, следовательно, нулем может быть только cj.
Таким образом, допущение о том, что cj 0 неверно и набор является линейно независимым.

Пример 5. Задан базис 3-х мерного векторного пространства:
{<-1, 2 ,3, 0>,<0, 1, 2, 1>,<2,-1,-1,1>}.
Скалярное произведение определено соотношением:
(<x1,x2,x3,x4>,<y1,y2,y3,y4>) = x1y1+x2y2+x3y3+x4y4.
Процедурой ортогонализации Грама Шмидта получаем систему векторов:
а1 = <-1, 2, 3, 0>; a2 = <0, 1, 2, 1>-4<-1, 2, 3,0>/7=<4,-1, 2, 7>/7;
a3 =<2, -1, -1, 1>+<-1, 2, 3, 0> <4, -1, 2, 7>/5 =<7, 2, 1, -4>/10.
(a1,a2)= (1+4+9+0) = 14;
a1 E =a1/14;
a2-(a1E,a2)a1E=a2-(8/14)(a1/14)=a2 4a1/7;
Третий вектор читателю предлагается обработать самостоятельно.

Нормированные векторы получают вид:
a1 E =a1/14;
a2 E =<4, -1, 2, 7>/70;
a3 E =<7, 2, 1,-4>/70;

Ниже в примере 6 дается подробный развернутый процесс вычислений получения ортонормированного базиса из простого (взятого наугад).

Пример 6. Привести заданный базис линейного векторного пространства к ортонормированному виду.
Дано: векторы базиса



Подпространства векторных пространств


Структура векторного пространства

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

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

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

Если L расширение поля К, то L можно рассматривать как векторное (или линейное) пространство над полем К. Элементы поля L (т. е. векторы) образуют по сложению абелеву группу. Кроме того, каждый вектор а L может быть умножен на скаляр r K, и при этом произведение ra снова принадлежит L (здесь ra просто произведение в смысле операции поля L элементов r и а этого поля). Выполняются также законы
r(a+b) = ra+rb, (r+s)a = ra + rs, (rs)a = r(sa) и 1а = а, где r,s K, a,b L.

Сказанное позволяет предположить, что векторные пространства можно некоторым образом расчленять, выделять в них части, называемые подпространствами. Очевидно, что основным результатом при таком подходе является сокращение размерности выделяемых подпространств. Пусть в векторном линейном пространстве L выделены подпространства L1 и L2. В качестве базиса L1 выбирается меньший набор еi, i = 1(1)s1, s1 < s, чем в исходном L.

Оставшиеся базисные векторы порождают другое подпространство L2, называемое ортогональным дополнением подпространства L1. Будем использовать запись L = L1 + L2. Она означает не то, что все векторы пространства L принадлежат либо L1, либо L2,, а то, что любой вектор из L можно представить в виде суммы вектора из L1 и ортогонального ему вектора из L2.
Разбивается не множество векторов векторного пространства L, а размерность d(L) и набор базисных векторов. Таким образом, подпространством L1 векторного пространства L называется множество L1, его элементов (меньшей размерности), само являющееся векторным пространством относительно введенных в L операций сложения и умножения на число.

Каждое линейное векторное подпространство Li содержит нулевой вектор и вместе с любыми своими векторами содержит и все их линейные комбинации. Размерность любого линейного подпространства не превосходит размерности самого исходного пространства.

Пример 7. В обычном трехмерном пространстве подпространствами являются все прямые (размерность s =1) линии, плоскости (размерность s = 2), проходящие через начало координат. В пространстве Рn многочленов степени не выше n подпространствами будут, например, все Рk при k < n, так как складывая и умножая на числа многочлены степени, не выше k, снова будут получаться такие же многочлены.
Однако, каждое из пространств Рп содержится в качестве подпространств в пространстве Р всех многочленов с вещественными коэффициентами, а это последнее является подпространством пространства С непрерывных функций.

Матрицы одинакового типа над полем действительных чисел также образуют линейное векторное пространство, так как для них выполняются все аксиомы векторных пространств. Векторное пространство L2 наборов длины n, каждый из которых ортогонален подпространству L1 наборов длины п, образует подпространство L2, называемое нулевым пространством для L1. Другими словами, каждый вектор из L2 ортогонален каждому вектору из L1 и наоборот.

Оба подпространства L1 и L2 являются подпространствами векторного пространства L наборов длины п. В теории кодирования [4] каждое из подпространств L1 и L2 порождает линейный код, двойственный по отношению к коду, порожденному другими подпространства-ми. Если L1 есть (п, k)-код, то L2 это (п, п k)-код. Если код является векторным пространством строк некоторой матрицы, то двойственный к нему код нулевое пространство этой матрицы и наоборот.

Важным вопросом при изучении векторных пространств Vn является установление их структуры (строения). Другими словами, интерес представляют элементы, их совокупности (подпространства размерности 1<k<п ), а также их отношения (упорядоченность, вложенность и т.п.). Будем считать заданным векторное пространство Vn над конечным полем GF(q), образованным q = р r элементами, где р простое число, r целое.
Известны следующие результаты.

Количества подпространств векторного пространства


Приведем следующее обоснование. Каждый вектор v1 0 из системы k линейно независимых ( v1,v2,,vk ) векторов может быть выбран qn 1 способами. Следующий вектор v2 0 не может быть выражен линейно через v1, т.е. может быть выбран qn q способами и т.д.

Последний вектор vk 0 также линейно не выражается через предыдущие выбранные векторы v1,v2,,vk и, следовательно, может быть выбран qn qk 1 способами. Общее число способов для выбора совокупности векторов v1,v2,,vk, таким образом, определится как произведение числа выборов отдельных векторов, что и дает формулу (1). Для случая, когда k = п, имеем wп = wn, n и из формулы (I) получаем формулу (2).



Важные обобщающие результаты о размерностях подпространств.
Совокупность всех наборов длины n, ортогональных подпространству V1 наборов длины n, образует подпространство V2 наборов длины n. Это подпространство V2 называется нулевым пространством для V1.
Если вектор ортогонален каждому из векторов, порождающих подпространство V1, то этот вектор принадлежит нулевому пространству для V1.
Примером (V1) может служить множество 7-разрядных векторов порождающей матрицы (7,4)-кода Хемминга, с нулевым подпространством (V2) 7-разрядных векторов, образующих проверочную матрицу этого кода.

Если размерность подпространства (V1) наборов длины n равна k, то размерность нулевого подпространства (V2) равна n k.
Если V2 подпространство наборов длины n и V1 нулевое пространство для V2, то (V2) нулевое пространство для V1.
Пусть UV обозначает совокупность векторов, принадлежащих одновременно U и V, тогда UV является подпространством.
Пусть UV обозначает подпространство, состоящее из совокупности всех линейных комбинаций вида au +bv, где u U, v V, a b числа.
Сумма размерностей подпространств UV и UV равна сумме размерностей подпространств U и V.
Пусть U2 нулевое подпространство для U1, а V2 -нулевое пространство для V1. Тогда U2V2 является нулевым пространством для U1V1.

Заключение


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

Литература


1. Авдошин С.М., Набебин А.А. Дискретная математика. Модулярная алгебра, криптография, кодирование. М.: ДМК Пресс, 2017. -352 с.
2. Акимов О.Е. Дискретная математика.Логика, группы, графы- М.: Лаб.Баз. Зн., 2001. -352 с.
3. Андерсон Д.А. Дискретная математика и комбинаторика.- М.: Вильямс, 2003. -960 с.
4. Берлекэмп Э. Алгебраическая теория кодирования. -М.: Мир,1971.- 478 с.
5. Ваулин А.Е. Дискретная математика в задачах компьютерной безопасности. Ч 1- СПб.: ВКА им. А.Ф. Можайского, 2015. -219 с.
6. Ваулин А.Е. Дискретная математика в задачах компьютерной безопасности. Ч 2- СПб.: ВКА им. А.Ф. Можайского, 2017. -151 с.
7. Горенстейн Д. Конечные простые группы. Введение в их классификацию.-М.: Мир,1985.- 352 с.
7. Грэхем Р., Кнут Д., Пташник О. Конкретная математика.Основание информатики.-М.: Мир,1998.-703 с.
9. Елизаров В.П. Конечные кольца.- М.: Гелиос АРВ,2006. 304 с.
Иванов Б.Н. Дискретная математика: алгоритмы и программы-М.: Лаб.Баз. Знаний., 2001. -280 с.
10. Ерусалимский Я.М. Дискретная математика: теория, задачи, приложения-М.: Вузовская книга, 2000.-280 с.
11. Корн Г., Корн Т. Справочник по математике для научных работников и инженеров.-М.: Наука, 1973.-832 с.
12. Лидл Р., Нидеррайтер Г. Конечные поля: В 2-х т. Т.1 -М.: Мир,1988. 430 с.
13. Лидл Р., Нидеррайтер Г. Конечные поля: В 2-х т. Т.2 -М.: Мир,1988. 392 с.
14. Ляпин Е.С., АйзенштатА.Я., Лесохин М.М., Упражнения по теории групп.- М.: Наука,1967.-264 с.
15. Муттер В.М. Основы помехоустойчивой телепередачи информации. -Л. Энергоатомиздат,1990.- 288 с.
16. Набебин А.А.Дискретная математика.- М.: Лаб.Баз. Знаний., 2001. -280 с.
17. Новиков Ф.А. Дискретная математика для программистов.- СПб.: Питер, 2000. -304 с.
18. Розенфельд Б.А. Многомерные пространства.-М.: Наука,1966.-648 с.
18. Холл М. Теория групп.-М.: Изд. ИЛ, 1962.- 468 с.
19. Шиханович Ю.А. Группы, кольца, решётки. СПб.: Кирцидели,2006. 368 с.
20. Шнеперман Л.Б. Курс алгебры и теории чисел в задачах и упражнениях: В 2-х ч Ч.2.-Мн.: Выш. шк., 1987. -256 с.
21. Шнеперман Л.Б. Сборник задач по алгебре и теории чисел.- Минск: Дизайн ПРО, 2000. -240 с.
Подробнее..

Не баян ищем дубликаты изображений на основе Milvus с индексом FAISS внутри

22.12.2020 18:11:09 | Автор: admin


В user-generated проектах часто приходится бороться с дубликатами, а для нас это особенно актуально, так как основной контент мобильного приложения iFunny это изображения, которые постятся десятками тысяч ежедневно. Для поиска повторов мы написали отдельную систему, чтобы облегчить процесс и сэкономить море времени.

Под катом рассмотрим используемые инструменты, а потом перейдём к примеру реализации.

Свёрточная нейронная сеть (СNN)


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

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

Есть и другой недостаток. На выходе классификации получается большой вектор (2048 float для resnet152), который где-то нужно хранить и иметь возможность за разумный промежуток времени найти все N похожих векторов для искомого что само по себе уже непросто.

FAISS


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

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

Milvus


Для этого есть весьма перспективный проект Milvus, который по дизайну сильно напоминает Elasticsearch. Отличие только в том, что Elasticsearch построен вокруг индекса lucene, а в Milvus вся архитектура выстроена вокруг индекса FAISS.

Структура коллекций тоже схожа:



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

Информация о коллекциях, партициях и сегментах хранится в отдельной SQL-базе. Для standalone-запуска используется встроенный SQLite, а ещё есть возможность использовать внешнюю MySQL-базу.



Проект Milvus находится в активной разработке (текущая версия 0.11.0). Пока что в нём нет репликации данных, как и возможности использовать другие SQL (или NoSQL) базы в качестве хранилища метаинформации. Поэтому пока для HA-решений можно использовать только схему с двумя экземплярами с общим хранилищем: один будет запущен, а другой спать. Для масштабирования можно будет использовать Mishards, но в 0.11.0 он сломан.

Кроме того, в 0.11.0 появилась возможность вместе с самим вектором и id сохранять в коллекцию дополнительные данные. Правда, пока без дополнительных индексов для них, но с возможностью поиска.

С точки зрения использования, Milvus выглядит как обычная внешняя база данных. Есть API (gRPC-клиент и набор http-методов) для сохранения и поиска вектора, управления коллекциями и индексами, а также для получения информации обо всех сущностях.

При создании коллекции можно указать максимальное количество записей в сегменте (segment_row_limit). Если превысить этот лимит, то Milvus начнёт строить индекс FAISS. С этим связана одна из особенностей Milvus: для всех добавляемых векторов, по которым ещё не создан индекс, поиск будет работать на основе полного перебора. Поэтому при больших значениях segment_row_limit будет много записей, для которых индекс ещё не построен (он также влияет ещё и на то, сколько будет созданных сегментов для коллекции). Для поиска похожих векторов в коллекции необходимо сделать поиск в каждом сегменте и чем их больше, тем дольше поиск.

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

Несмотря на все особенности, поиск по векторам работает быстро. Архитектура индексов FAISS и самого Milvus позволяет за раз искать одновременно значения по нескольким векторам. И на практике последовательный поиск двух векторов будет существенно медленнее поиска обоих векторов за раз.

Реализация поиска дубликатов


Milvus можно запускать как в CPU-версии, так и в GPU. Первую лучше всего использовать на процессорах, которые поддерживают инструкцию AVX512. Для этого достаточно просто запустить контейнер:

docker run -d --rm --name milvusdb -p 19530:19530 -p 19121:19121 \     milvusdb/milvus:0.11.0-cpu-d101620-4c44c0

В данном случае 19530 будет портом для gRPC-клиента, а 19121 для http API.

В качестве CNN-сети можно взять любую из предобученных (или обучить самому) результаты могут немного отличаться. В данном примере будем использовать предобученный resnet152:

model = models.resnet152(pretrained=True)

Вектор будем снимать со слоя `avgpool`:

layer = model._modules.get('avgpool')

А сам вектор получать с помощью hook:

vector = torch.zeros(2048)def copy_data(m, i, o):    vector.copy_(torch.reshape(o.data, (1, 2048))[0])hook = layer.register_forward_hook(copy_data)model(prepared_image)hook.remove()

Полный код получения вектора выглядит так:

import numpy as npimport torchimport torchvision.models as modelsimport torchvision.transforms as transformsfrom torch.autograd import Variablefrom PIL import Imagemodel = models.resnet152(pretrained=True)layer = model._modules.get('avgpool')model.eval()pipeline = [    transforms.Resize(224),    transforms.ToTensor(),    transforms.Normalize(mean=[0.485, 0.456, 0.406],                         std=[0.229, 0.224, 0.225]),]def _prepare_Image(img: Image) -> Variable:    raw = img    for action in pipeline:        raw = action(raw)    return Variable(raw.unsqueeze(0))def image_vectorization(image_path: str) -> np.ndarray:    img = Image.open(image_path)    prepared_image = _prepare_Image(img)    vector = torch.zeros(2048)    def copy_data(m, i, o):        vector.copy_(torch.reshape(o.data, (1, 2048))[0])    hook = layer.register_forward_hook(copy_data)    model(prepared_image)    hook.remove()    # vector normalization    norm_vector = vector / torch.norm(vector)    return np.array(norm_vector)

Теперь понадобится клиент для работы с Milvus. Можно взять любой из поддерживаемых (Python, Java, Go, Rest, C++). Возьмём Java-клиент и напишем пример на Kotlin. Почему? А почему бы и нет.

Подключаем Milvus SDK:

implementation("io.milvus:milvus-sdk-java:0.9.0")

Создаём подключение к Milvus:

val connectParam = ConnectParam.Builder()        .withHost("localhost")        .withPort(19530)        .build()val client = MilvusGrpcClient(connectParam)

Создаём коллекцию под 2048 вектор:

val collectionMapping = CollectionMapping.create(collectionName)            .addVectorField("float_vec", DataType.VECTOR_FLOAT, 2048)          //выключаем автосоздание id            .setParamsInJson(JsonBuilder()                  .param("auto_id", false)                  .param("segment_row_limit", segmentRowLimit)                  .build()            )        client.createCollection(collectionMapping)

Создаём IVF_SQ8 индекс:

    Index.create(collectionName, "float_vec")            .setIndexType(IndexType.IVF_SQ8)            .setMetricType(MetricType.L2)            .setParamsInJson(JsonBuilder()                    .param("nlist", 16384)                    .build()            )     client.createIndex(index)

Сохраняем несколько векторов в коллекцию:

InsertParam.create(collectionName)            .setEntityIds(listOf(1L, 2L))            .addVectorField("float_vec", DataType.VECTOR_FLOAT, listOf(vector1, vector2))client.insert(insertParam)client.flush(collectionName)  // чтобы сразу можно было найти  вектор

Ищем ранее сохранённый вектор:

val dsl = JsonBuilder().param(            "bool", mapOf(                "must" to listOf(                    mapOf(                        "vector" to mapOf(                            "float_vec" to                                mapOf(                                    "topk" to 10,                                    "metric_type" to MetricType.L2,                                    "type" to "float",                                    "query" to listOf(vector1),                                    "params" to mapOf("nprobe" to 50)                                )                        )                    )                )            )        ).build() val searchParam = SearchParam.create(collectionName)       .setDsl(dsl) val result = client.search(searchParam) println(result.queryResultsList[0].map { it.entityId to it.distance })

Если всё работает и правильно настроено, то вернётся похожий результат:

[(1, 0.0), (2, 0.2)]

Для первого вектора расстояние L2 с самим собой будет 0, а с другим вектором больше 0.

Всё вышеприведённое, конечно, только наброски, но этого достаточно, чтобы попробовать создать Python-сервис для классификации и получения вектора. И либо для него накрутить API для сохранения и поиска векторов, либо сделать в отдельном сервисе (например, на Kotlin), который будет получать вектор и сохранять его уже в Milvus самостоятельно.

Спасибо всем, кто дочитал до конца, надеюсь, вы нашли для себя что-то новое. А если вас заинтересовал проект Milvus, то можете поддержать его на Github.
Подробнее..

Почему мы трансформируем трёхмерные векторы матрицами 4х4?

03.02.2021 08:16:01 | Автор: admin

Почему не матрица 3х3? Почему в матрице 4х4 всё уложено именно так? Зачем там последняя строка, заполненная нулями и одной единицей в конце? Этими вопросами я задался накануне, решил поисследовать вопрос и рассказываю что выяснил.

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

Афинное преобразование является композицией двух функций: линейной и нелинейной трансформаций. Через линейные реализуются вращение и масштабирование, а сама трансформация задается матрицей той же размерности, что и пространство, в котором она применяется (Ax). Через нелинейные реализуются перемещения, но из свойства таковы, что такие трансформации не могут быть выражены матрицей, зато легко могут быть выражены слагаемым вектором (+b).

Афинное преобразование T, примененное на вектор x можно записать как

T(\vec{x}) = A\vec{x}+\vec{b}

Трансформации одномерного вектора

Благорадя одномерности для простоты мы можем представить одномерную матрицу А, вектор b и вектор x как числа на вещественной прямой. Так же трансформированное значение x предпочту записывать как x', мне кажется так выглядит чуть более чисто:

\begin{array}{ll} A\rightarrow [a] \rightarrow a, \\ \vec{b} \rightarrow (b) \rightarrow b, \\ \vec{x} \rightarrow x, \\ T(x) \rightarrow x' \end{array}

Итого

x' = ax+b

Через манипуляции с а мы можем растягивать или сжимать вектор x (линейно трансформировать), а через манипуляции с b перемещать (нелинейно трансформировать).

Случаи, когда используются обе, линейная и нелинейная трансформации вместе довольно частые. Было бы удобно найти такое одно преобразование M, чтобы выразить в нём сразу оба:

x' = ax+b = M(x)

Возьмём для примера трансформацию x' = 3x + 4 (3x линейная трансформация и +4 нелинейная трансформация) и попробуем подобрать нужную матрицу.

\begin{array}{ll} Mx = 3x + 4\\ M = (3x+4)/x\\M=3+(\frac{4}{x})\end{array}

Свойства линейных трансформаций таковы, что они могут быть выражены через матрицы (например преобразование 3x может быть выражено через одномерную матрицу [3]), однако нелинейные трансформации (x+4) таких свойств лишены, от чего не удается выразить M без зависимости от x.

Трюк: поднимается на размерность выше

Если представить +4 как +4y, введя дополнительную координату y, выразив её так же через x и саму себя, то получится система линейных уравнений

x' = 3x + 4y \\ y' = \_x + \_y

которую можно выразить через матрицу 2x2, которая в свою очередь может выразить x' = 3x+4 и при этом не будет зависеть от x, т.е будет линейной трансформацией. Нижнюю строку я не заполнил конкретными числами, потому что на данный момент они не важны.

\begin{bmatrix} x'\\ y' \end{bmatrix} = \begin{bmatrix} 3 & 4 \\ \_ & \_ \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix}

Так как матрица 2x2 умножается только на двумерный вектор, то необходимо предоставить не только х, но и вторую координату - y, а так как она учавствует в выражении +4y и мы хотим, чтобы это превратилось просто в +4, то вместе с неизвестным x на умножение с матрицей передаем единицу:

\begin{bmatrix} x'\\y' \end{bmatrix}= \begin{bmatrix} 3 & 4\\ \_ & \_ \end{bmatrix} \begin{bmatrix} x \\ 1 \end{bmatrix} \rightarrow \begin{array}{l} x' = 3\cdot x + 4\cdot 1\\y' = \_\cdot x + \_\cdot 1 \end{array}

Второе выражение в системе нам не интересно, оно введено только для того, чтобы иметь возможность получить матрицу, однако в результате вычислений будет возвращен двумерный вектор, с 3x+4 для x' и чем-то для y' и было бы сподручнее получить единицу в y' вместо непонятно чего, ведь в таком случае мы получим удобный вектор

\begin{bmatrix} x'\\1 \end{bmatrix}

который будет удобно умножать на любую другую матрицу далее. Чтобы получить единицу заполняем выражение соответствующими коэффициентами: y' = 1 = 0 x + 1 1

\begin{bmatrix} x'\\1 \end{bmatrix}= \begin{bmatrix} 3 & 4\\ 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ 1 \end{bmatrix}

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

\begin{bmatrix} a & b\\0 & 1 \end{bmatrix}

Получается в матрице заключена линейная трансформация (a), нелинейная трансформация (b) и служебная строка (0 1) которая сохраняет для y' значение 1, чтобы вычисления x' проходили так, как мы ожидаем.

На самом деле трансформация - это просто хитрое слово, обозначающее функцию, но предполагаящая отображение некоторого движения. Вот как трансформация из примера выглядит визуально (https://www.geogebra.org/calculator/jvesjzyw):

\begin{bmatrix} 3 & 4 \\ 0 & 1 \end{bmatrix} \begin{bmatrix} 1 \\ 1 \end{bmatrix} = \begin{bmatrix} 7 \\ 1 \end{bmatrix}

Тот же трюк, но в двумерном пространстве

Имеем матрицу для вращения или масштабирования и вектор для перемещения

Чтобы иметь возможность задать матрицей оба преобразования поднимается на размерность выше и выпоняет принципиально те же действия, что в одномерном случае, только теперь новая компонента - это z, потому что y уже существует и нужна.

Матрица линейной трансформации выросла до 2х2 по понятным причинам двумерности пространства. Вектор b тоже вырос до двумерного и способен перемещать по обеим осям.

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

В трёхмерном пространстве ничего нового

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

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

Полезные материалы

Computing 2D affine transformations using only matrix multiplication

https://medium.com/hipster-color-science/computing-2d-affine-transformations-using-only-matrix-multiplication-2ccb31b52181

Brilliant. Linear Transformations

https://brilliant.org/wiki/linear-transformations/

Explaining Homogeneous Coordinates & Projective Geometry

https://www.tomdalling.com/blog/modern-opengl/explaining-homogenous-coordinates-and-projective-geometry/

Nonlinear Transformation

https://stattrek.com/statistics/dictionary.aspx?definition=Nonlinear-Transformation

Can non-linear transformations be represented as Transformation Matrices?

https://math.stackexchange.com/a/455

Linear transformations and matrices | Essence of linear algebra, chapter 3

https://youtu.be/kYB8IZa5AuE

Подробнее..

Перевод Сравнение векторных расширений ARM и RISC-V

20.05.2021 22:11:13 | Автор: admin

Сравнение векторного расширения RISC-V (RVV) и масштабируемого векторного расширения ARM (SVE/SVE2).

Микропроцессоры с векторными командами ожидает большое будущее. Почему? Беспилотные автомобили, распознавание речи, распознавание образов, всё это основано на машинном обучении, а машинное обучение на матрицах и векторах.

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


Увеличение производительности остановилось, что делает необходимым распараллеливать вычисления различными способами, либо с помощью многоядерности, либо с помощью векторизации, либо с помощью исполнения не в порядке очереди (out-of-order).Увеличение производительности остановилось, что делает необходимым распараллеливать вычисления различными способами, либо с помощью многоядерности, либо с помощью векторизации, либо с помощью исполнения не в порядке очереди (out-of-order).

Сейчас мы придумали тысячи умных способов получить большую производительность, будь то создание многоядерных процессоров, внеочередное (out-of-order) исполнение, более совершенное предсказание переходов и SIMD-команды.

Все эти способы основаны на одной центральной идее: пытаться различными способами распараллеливать работу. Когда вы выполняете какие-то вычисления в цикле над массивом элементов, у вас появляется возможность параллелизма данных. Этот цикл при достаточно умном компиляторе может быть превращён в последовательность SIMD или векторных команд.

SIMD-инструкции, в отличие от SISD-инструкций, каждая инструкция (зелёный цвет) обрабатывает множество независимых потоков данных (синий цвет).SIMD-инструкции, в отличие от SISD-инструкций, каждая инструкция (зелёный цвет) обрабатывает множество независимых потоков данных (синий цвет).

SIMD-команды, такие, как Neon, MMX, SSE2 и AVX замечательно сработали в мультимедийных приложениях, в таких вещах, как кодирование видео и т.п. Но нам нужно получить большую производительность во многих областях. Векторные команды предлагают большую гибкость в превращении почти любого цикла в векторные команды. Однако есть много различных способов это сделать.

Я описал векторные команды RISC-V здесь:RISC-V Vector Instructions vs ARM and x86 SIMD.

Позже я описал векторные команды ARM:ARMv9: What is the Big Deal?.

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

Это заставило меня обнаружить, что ARM и RISC-V следуют принципиально разным стратегиям. Стоит написать об этом, потому что это одна из моих любимых тем. Я люблю простые, элегантные и эффективные технологии:The Value of Simplicity.

Векторное расширение RISC-V по сравнению с ARM SVE это элемент элегантности и простоты.

Проблема с масштабируемыми векторными командами ARM (Scalable Vector Instructions, SVE)

В процессе изучения SVE, было неочевидно, почему это так трудно для понимания, но когда я взял книгу по RISC-V и перечитал главу по векторному расширению, это стало ясно.

Честно говоря, ARM является большим шагом вперёд по сравнению с большим сложным и беспорядочным ассемблером Intel x86. Давайте не будем про это забывать. Также мы не можем пройти мимо того факта, что ARM не молодая платформа, и содержит много легаси. Когда мы имеем дело с ARM, у нас есть три различных набора команд: ARM Thumb2, ARM32 и ARM64. Когда вы гуглите руководства и пытаетесь их читать, возникает ряд проблем. Люди не всегда понимают, какой набор команд изучать.

Инструкции Neon SIMD имеют две разновидности: 32- и 64-битные. Проблема, конечно, не в ширине слова, а в том, что для 64-битной архитектуры ARM перепроектировал весь набор команд и изменил многие вещи, даже соглашение об именовании регистров.

Вторая проблема в том, что ARM большой. Система команд содержит свыше 1000 команд. Сравните с базовым набором RISC-V, в котором всего лишь 48 команд. Это означает, что читать ассемблер ARM не так просто. Посмотрим на команду SVE:

LD1D z1.D, p0/Z, [x1, x3, LSL #3]

Здесь делается много. Если у вас есть опыт в ассемблере, вы можете догадаться, что префиксLDозначаетLoaD. Но что означает1D? Вы должны это выяснять. Дальше вы должны выяснить, что означают странные суффиксы имён регистров, такие как .Dand/Z. Дальше вы видите скобки[]. Вы можете догадаться, что они составляют адрес, зачем там странная запись LSL #3, что означает логический сдвиг влево (Logic Shift Left)три раза. Что сдвигается? Все данные? Или только содержимое регистраx3? Это снова нужно смотреть в справочнике.

Команды ARM SVE содержат множество концепций, не являющихся очевидными, от которых голова идёт кругом. Мы сделаем глубокое сравнение, но сначала скажем несколько слов о RISC-V.

Красота векторного набора команд RISC-V

Обзор всех команд векторных расширений RISC-V (RVV) помещается на одной странице. Команд немного, и, в отличие от ARM SVE, они имеют очень простой синтаксис. Вот команда загрузки вектора в RISC-V:

VLD v0, x10

Команда загружает векторный регистрvданными, находящимися по адресу, который хранится в обычном целочисленном регистреx10. Но сколько данных загружается? В наборе команд SIMD, таком, как ARM Neon это определяется именем векторного регистра.

LD1 v0.16b, [x10]  # Load 16 byte values at address in x10

Есть другой способ сделать это. Такой же результат достигается таким образом:

LDR d0, [x10]    # Load 64-bit value from address in x10

Эта команда загружает младшую 64-битную часть 128-битного регистраv0. Для SVE2 у нас есть другой вариант:

LD1D z0.b, p0/z, [x10] # Load ? number of byte elementsLD1D z0.d, p0/z, [x10] # Load double word (64-bit) elements

В этом случае регистр предикатаp0определяет в точности, сколько элементов мы загружаем. Еслиp0 = 1110000, мы загружаем три элемента.v0 это 128-битная младшая частьz0.

Регистры имеют одинаковые имена?

Причина этому в том, что регистры d,vиz находятся в одной ячейке. Давайте поясним. У вас есть блок памяти, называемый регистровый файл в каждом CPU. Или, если быть более точным, в CPU расположено много регистровых файлов. Регистровый файл, это память, в которой расположены регистры. Вы не можете получить доступ к ячейкам памяти в регистровом файле, так же как в обычной памяти, вместо этого вы обращаетесь к области памяти, используя имя регистра.

ARM floating point registers are overlapping in the same register file (memory in CPU holding registers).ARM floating point registers are overlapping in the same register file (memory in CPU holding registers).

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

  • z3 регистр SVE2 переменной длины.

  • v3 младшие 128 бит z3. Регистр Neon.

  • d3 младшие 64 битаv3.

  • s3 младшие 32 битd3

RISC-V, однако, устроен не так. Векторные регистры RISC-V находятся в отдельном регистровом файле, не разделяемом с регистрами скалярной плавающей точки.

  • x0-x31 скалярные целочисленные регистры.

  • f0-f31 скалярные регистры с плавающей точкой.

  • v0-v31 векторные регистры. Длина не зависит от ISA.

Сложность векторных команд ARM

Я только поцарапал поверхность векторных команд ARM, потому что их очень много. Просто найти, что делает команда загрузки Neon и SVE2, занимает много времени. Я просмотрел много документации ARM и записей в блогах. Сделать то же самое для RISC-V очень просто. Практически все команды RISC-V можно разместить на двойном листе бумаги. У него есть только три команды загрузки вектораVLD,VLDSиVLDX.

Я не могу сказать, сколько этих команд у ARM. Их очень много, и я не собираюсь становиться профессионалом по программированию ARM. на ассемблере.

Как ARM и RISC-V обрабатывают вектора переменной длины

Это довольно интересный вопрос, так как ARM и RISC-V используют существенно различные подходы и я считаю, что простота и гибкость решения RISC-V просто блестящая.

Вектора переменной длины в RISC-V

Чтобы начать обработку векторов, вы делаете две вещи:

  • VSETDCFG Vector SET Data ConFiGuration. Устанавливает битовый размер каждого элемента, тип, который может быть вещественным, знаковым целым или беззнаковым целым. Также конфигурация определяет, сколько векторных регистров используется.

  • SETVL SET Vector Length. Устанавливает, сколько элементов содержит вектор. Максимальное количество элементов, которое вы не можете превысить MVL(max vector length).

Регистровый файл RISC-V может быть скофигурирован так, чтобы иметь меньше 32 регистров. Может быть, например, 8 регистров или 2 регистра большего размера. Регистры могут занимать весь объём регистрового файла.Регистровый файл RISC-V может быть скофигурирован так, чтобы иметь меньше 32 регистров. Может быть, например, 8 регистров или 2 регистра большего размера. Регистры могут занимать весь объём регистрового файла.

И здесь всё становится интереснее. В отличие от ARM SVE, я могу разделить файл векторных регистров именно так, как я хочу. Пусть регистровый файл имеет размер 512 байт. Я могу теперь объявить, что я хочу иметь два векторных регистра, по 256 байт каждый. Далее я могу сказать, что я хочу использовать 32-битные элементы, другими словами, элементы по 4 байта. Получаем следующее:

Два регистра: 512 байт / 2 = 256 байт на регистр256 байт / 4 байта на элемент = 128 элементов

Это означает, что я могу складывать или умножать 128 элементов просто одной командой. В ARM SVE вы этого сделать не можете. Количество регистров фиксировано, и память аллоцирована для каждого регистра. И RISC-V, и ARM позволяют вам использовать максимум 32 векторных регистра, но RISC-V позволяет вам отключать регистры и отдавать используемую ими память оставшимся регистрам, увеличивая их размер.

Вычисление максимальной длины вектора (Max Vector Length, MVL)

Давайте посмотрим, как это работает на практике. Процессор, конечно, знает размер регистрового файла. Программист этого не знает, и не предполагается, что знает.

Когда программист использует VSETDCFG, чтобы установить типы элементов и количество используемых регистров, процессор использует эту информацию, чтобы вычислить максимальную длину вектора Max Vector Length (MVL).

LI        x5, 2<<25  # Load register x5 with 2<<25VSETDCFG  x5         # Set data configuration to x5

В примере выше происходят две вещи:

  • Включаем два регистра:v0иv1.

  • Устанавливаем тип элементов в 64-битные вещественные числа. Давайте сравним это с ARM Neon, в котором каждый регистр имеет длину 128 бит. Это означает, что Neon может обрабатывать два таких числа параллельно. Но в RISC-V 16 таких регистров можно объединить в один. Это позволяет обрабатывать 32 значения параллельно.

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

Итак, мы получили значениеMVL, равное 32. Разработчик не должен напрямую знать это число. Команда SETVLработает так:

SETVL rd, sr  ; rd  min(MVL, sr), VL  rd

Если вы попытаетесь установить Vector Length (VL)в значение 5, это сработает. Однако, если вы попытаетесь установить значение 60, вы получите вместо этого значение 32. Итак, величина Max Vector Length (MVL) важна, она не фиксирована конкретным значением при изготовлении процессора. Она может быть вычислена исходя из конфигурации (типа элементов и количества включенных регистров).

Вектора переменной длины в ARM

В ARM вы не устанавливаете длину вектора явным образом. Вместо этого вы устанавливаете длину вектора косвенно, используя предикатные регистры. Они являются битовыми масками, которыми вы включаете и выключаете элементы в векторном регистре. Регистры предикатов также существуют в RISC-V, но не имеют центральной роли, как в ARM.

Чтобы получить эквивалентSETVLна ARM , используйте командуWHILELT, что является сокращением отWhile Less Than:

WHILELT p3.d, x1, x4

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

i = 0while i < M   if x1 < x4      p3[i] = 1   else      p3[i] = 0  end  i += 1  x1 += 1end

Концептуально, мы переворачиваем биты в регистре предиката p3в зависимости от того, меньше лиx1,чемx4. В данном случаеx4содержит длину вектора. Еслиp3выглядит так, то длину вектора можно считать равной 3.

1110000

То есть вектор переменной длины реализуется за счёт того, что все операции используют предикат. Рассмотрим эту операцию сложения. Представьте, чтоv0[p0]извлекает из v0только те элементы, для которыхp0истинно.

ADD v4.D, p0/M, v0.D, v1.D ; v4[p0]  v0[p0] + v1[p0]

Итак, мы сделали некоторое вступление. Сейчас рассмотрим более полный пример кода, чтобы увидеть, как эти наборы команд работают на практике.

Пример кода DAXPY

Рассмотрим сейчас, как функции C могут быть реализованы различными векторными командами:

void daxpy(size_t n, double a, double x[], double y[]) {        for (int64_t i = 0; i < n; ++i) {                y[i] = x[i] * a + y[i];        }}

Почему такое странное имя daxpy? Это простая функция в библиотеке линейной алгебры BLAS, популярной в научной работе. В BLAS эта функция называется daxpyи она очень популярна для демонстрации примеров работы разнообразных SIMD и векторных команд. Она реализует такую формулу:

aX + Y

гдеa скаляр, а XиY вектора. Без векторных команд нужно было бы обрабатывать все элементы в цикле. Но с умным компилятором, эти команды могут быть векторизованы в код, который выглядит на RISC-V так, как показано ниже. Комментарии показывают, какой регистр какой переменной соответствует:

daxpy(size_t n, double a, double x[], double y[]) n - a0  int   register (alias for x10) a - fa0 float register (alias for f10)  x - a1  (alias for x11)  y - a2  (alias for x12

Код:

LI       t0, 2<<25    VSETDCFG t0             # enable two 64-bit float regsloop:    SETVL  t0, a0           # t0  min(mvl, a0), vl  t0    VLD    v0, a1           # load vector x    SLLI   t1, t0, 3        # t1  vl * 2 (in bytes)    VLD    v1, a2           # load vector y    ADD    a1, a1, t1       # increment pointer to x by vl*8    VFMADD v1, v0, fa0, v1  # v1 += v0 * fa0 (y = a * x + y)    SUB    a0, a0, t0       # n -= vl (t0)    VST    v1, a2           # store Y    ADD    a2, a2, t1       # increment pointer to y by vl*8    BNEZ   a0, loop         # repeat if n != 0    RET    

Это код, скопированный из примера. Отметим, что мы не используем именаf иxдля целочисленных и вещественных регистров. Чтобы помочь разработчикам лучше помнить соглашения, ассемблер RISC-V определяет ряд псевдонимов. Например, аргументы функции передаются в регистрахx10-x17. Но нет необходимости запоминать эти номера, для аргументов предусмотрены псевдонимыa0-a7.

t0-t6 псевдонимы регистров временных переменных. Они не сохраняются между вызовами.

Для сравнения мы приведём ниже код ARM SVE. Пометим, какой регистр какую переменную содержит.

daxpy(size_t n, double a, double x[], double y[]) n - x0  register a - d0  float register x - x1  register  y - x2  register i - x3  register for the loop counter

Код:

daxpy:        MOV z2.d, d0            // a        MOV x3, #0              // i        WHILELT p0.d, x3, x0    // i, nloop:        LD1D z1.d, p0/z, [x1, x3, LSL #3] // load x        LD1D z0.d, p0/z, [x2, x3, LSL #3] // load y        FMLA z0.d, p0/m, z1.d, z2.d        ST1D z0.d, p0, [x2, x3, LSL #3]        INCD x3                 // i        WHILELT p0.d, x3, x0    // i, n        B.ANY loop        RET

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

LD1D z1.d, p0/z, [x1, x3, LSL #3]

Часть в квадратных скобках вычисляет адрес, из которого происходит загрузка:

[x1, x3, LSL #3] = x1 + x3*2 = x[i * 8]

Итак, здесь видно, чтоx1представляет базовый адрес переменнойx.x3 счётчикi. Сдвигом влево на три бита мы умножаем на 8, то есть на количество байт в 64-битном вещественно числе.

Заключение

Как начинающий в векторном кодинге, я должен сказать, что ARM переусложнён. Это не значит, что ARM плохой. Я также изучал систему команд Intel AVX, и она в 10 раз хуже. Я совершенно определённо не хочу тратить время на изучение AVX, принимая во внимание, сколько усилий отняли SVE и Neon.

Для меня совершенно ясно, что любой, кто хочет изучать кодинг на ассемблере, должен начать с RISC-V. Для начинающих это на порядки проще в освоении. И это не удивительно. Эта система команд специально разработана для преподавания в университете.

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

Если для вас, как и для меня, это хобби, и вы просто хотите понимать, как развивается технология, и как работают вещи, такие, как векторная обработка, сберегите свои усилия и просто прочитайте книгу по RISC-V.

Люди могут поспорить, что ARM или Intel или что-то ещё проще, потому что по ним больше книг и больше ресурсов. Ничего подобного! Я могу сказать вам на своём собственном опыте, что документация часто представляет собой препятствие, а не помощь. Это означает, что вам нужно раскопать больше материала. Вы найдёте много противоречий, корни которых лежат в устаревших принципах работы.

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

Подробнее..

Шаблон удостоверяющей печати, когда нужно правильно и не как у всех

14.05.2021 22:04:58 | Автор: admin

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

Началось всё в 2009 году, когда вместо того, чтобы, для документов в электронном виде, отсканировать печать (как это обычно делается), я, по разным причинам (включая уже заметную на тот момент деформацию полимера действующей печати), запланировал отрисовать её заново. Но перед этим решил проверить: не была ли она сделана при помощи одного из популярных генераторов. Моё предположение оказалось верным и, через несколько минут, печать, со 100% точностью, я получил просто, выбрав подходящий шрифт и введя нужные данные в поля программы. Результат выглядел примерно так:

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

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

Флэш технологию часто называют новой, что не совсем верно: первые серийные образцы оборудования для производства красконаполненных печатей по флэш технологии появились в 1964 году в Японии. Создаваемые по этой технологии печати могут иметь элементы разного цвета в полях произвольной формы. Вокруг полей разного цвета выдерживается определенное, зависящее от оборудования, минимальное расстояние. Такие печати имеют хорошую разрешающую способность, а их оснастки компактны и бесшумны при проставлении оттисков. Заполняются они краской устойчивой, после высыхания, к воздействию воды и спирта.

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

На следующем этапе нужно было определить минимально допустимую толщину линий и размер элементов микротеста для печати, но не найдя ничего конкретного, пришлось ориентироваться на ГОСТ Р 51511-2001, относящийся к печатям с воспроизведением государственного герба Российской Федерации, а именно на п. 6.2.3: Наличие линий толщиной 0,08+0,01 мм., и п. 6.2.1, 6.2.2: Размер элементов микротекста от 0,5 до 0,8 мм.

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

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

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

В целом результатом я был доволен, заказ оформлен, оплачен и, спустя какое-то время, получен. Пробные оттиски впечатляли (тот шаблон, к слову, используется до сих пор). Однако я не учёл особенности зрительного восприятия человеком объектов, когда они могу казаться больше или меньше, чем есть на самом деле.

То же самое изображение:

Так это выглядит на самом деле (одинаковый размер печатей):

Таким образом, при одинаковых оснастках (обычно 40 мм.), оттиск по моему шаблону визуально кажется меньше, чем оттиск обычной круглой печати. Избежать этого эффекта, в моем случае, можно было заказав печать на оснастке 42-45 мм.

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

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

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

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

Текущий проект оформлен таким образом, чтобы большая часть нового шаблона генерировалась автоматически при помощи скриптов. Таким образом можно получить бесконечное множество визуально одинаковых, но разных по сути шаблонов (для чего это может быть нужно, станет понятно позднее). Адаптацию одного из скриптов под свою версию Illustrator пришлось заказывать на стороне. Общий объем чистого проекта (в котором уже нет ничего лишнего) можно представить по следующим кадрам:

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

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

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru