Как составить матрицу по массиву

mas2=new int*[n]; — выделение памяти динамически под массив указателей на переменные типа int, размером n, и присвоение адреса этой памяти указателю mas2.
mas2[i]=new int[n]; — выделение памяти динамически под массив для переменных типа int, размером n, и присвоение адреса этой памяти указателю mas2[i].
Вообще строки 15-17 динамически выделяют память под двумерный массив (размером n*n), для хранения переменных типа int.
Для С аналог 15-17 строк будет выглядеть так:

C
1
2
3
  mas2 = (int **)malloc (n * sizeof (int *));
  for (i = 0; i < n; i++)
  mas2 [i] = (int *)malloc (n * sizeof (int));

но не забудьте подключить: #include <stdlib.h>

mas2[i][j]=(int)pow(j+1, i+1); — элементу массива mas2 (который расположен в строке i и столбце j) присваиваем значение, которое получится если j+1 возведем в степень i+1. Т.е. например элементу массива во второй строке и третьем столбце присвоим значение = 4 в степени 3.

cout.width(5); — при выводе на экран значений делаем между ними отступ на 5. Аналог в С: printf(«%5d», mas2[i][j]); — в этой функции выделяем 5 знакомест под вывод на экран каждого элемента mas2[i][j].

  • NumPy
  • Установка и первое знакомство
  • Основные типы данных. Создание массивов функцией array()
  • Функции автозаполнения, создания матриц и числовых диапазонов
  • Свойства и представления массивов, создание их копий
  • Изменение формы массивов, добавление и удаление осей
  • Объединение и разделение массивов
  • Индексация, срезы, итерирование массивов
  • Базовые математические операции над массивами
  • Булевы операции и функции, значения inf и nan
  • Базовые математические функции
  • Произведение матриц и векторов, элементы линейной алгебры
  • Множества (unique) и операции над ними
  • Транслирование массивов
  • Главная
  • Модули
  • NumPy

Функции автозаполнения, создания матриц и числовых диапазонов

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

np.array( [0]*10 )  # массив из 10 нулей
np.array( [1]*15 )  # массив из 15 единиц
np.array( [x for x in range(10)] ) # массив из чисел от 0  до 9

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

Функции автозаполнения элементов массива

Название

Описание

empty(shape, …)

Возвращает
новый массив заданного размера и типа данных, но без определенных значений.

eye(N,
M=None,
…)

Возвращает
массив размером NxMс единичными диагональными элементами
(остальные элементы равны нулю).

identity(n,
…)

Возвращает
квадратный массив размерностью nxn с единичными элементами по главной
диагонали (остальные равны нулю).

ones(shape, …)

Возвращает
массив заданного размера и типа, состоящего из всех единиц.

zeros(shape, …)

Возвращает
массив заданного размера и типа, состоящего из всех нулей.

full(shape,
value,
…)

Возвращает
массив заданного размера и типа со значениями value.

Это только часть
основных функций для создания массивов с заданными значениями. Использовать их
достаточно просто. Например, так:

np.empty(10) # создание одномерного массива с произвольными числами
np.empty(10, dtype='int16')
np.empty((3, 2), dtype='float32') # возвращаетматрицу 3x2 стипомfloat32

Для функций eye и identity
размерности указываются отдельными параметрами:

np.eye(4)    # матрица 4х4
np.eye(4, 2)         # матрица 4x2
np.identity(5) # матрица 5x5

Функции ones, zeros
и full работают по аналогии с функцией empty:

np.zeros( (2, 3, 4) ) # нулевая матрица размерностью 2x3x4
np.ones( [4, 3], dtype='int8') # матрица 4x3 из единиц и типом int8
np.full((3, 2), -1) # матрица 3x2, состоящая из -1

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

Функции создания матриц

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

Название

Описание

mat(object,
…)

Приводит
входные данные object к матрице, если это возможно. Параметр
object может быть
строкой, списком или кортежем.

diag(list, …)

Формирует
диагональную матрицу на основе списка или массива NumPy. В последних
версиях возвращает копию массива (а не его представление).

diagflat(list,
…)

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

tri(N,
M=None, …)

Создает
треугольный массив NxM с единицами на главной диагонали и
ниже ее.

tril(list,
…)

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

triu(list,
…)

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

vander(list,
N=None, …)

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

Давайте
посмотрим как работают эти функции.

np.mat('1 2 3 4') # создает матрицу 1x4 из строки
np.mat('1, 2, 3, 4') # то же самое: создает матрицу 1x4 из строки
np.mat('1 2; 3 4') # возвращает матрицу 2x2

Или же, вместо
строк можно использовать список или кортеж:

np.mat([5, 4, 3])
np.mat( [(1,2,3), (4,5,6)])

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

np.mat( [(1,2,3), (4,5,6,7)])# ошибка, размерности не совпадают

Следующая функция
позволяет формировать диагональные матрицы:

np.diag([1, 2, 3]) # диагональная матрица 3x3

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

np.diag([(1,2,3), (4,5,6), (7,8,9)]) # выделение элементов главной диагонали

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

np.diagflat([(1,2,3), (4,5,6), (7,8,9)])

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

np.tri(4) # треугольная матрица 4x4
np.tri(4, 2) # треугольная матрица 4x2

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

a = np.array( [(1,2,3), (4,5,6), (7,8,9)] )
np.tril(a) # нижняя треугольная матрица размером 3x3
np.triu(a) # верхняя треугольная матрица размером 3x3

Если указать
одномерный список:

то будет создана
треугольная матрица 3×3 из строк [1, 2, 3].

Также функции tril
и triu будут работать
и с многомерными массивами:

np.tril([[[1,2,3], [4,5,6], [7,8,9]]])
np.tril([[[1,2,3], [4,5,6], [7,8,9]], [[10,20,30], [40,50,60], [70,80,90]], [[100,200,300], [400,500,600], [700,800,900]]])

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

Последняя
функция этойгруппы формирует матрицу Вандермонда из одномерных списков или
массивов:

np.vander([1,2,3]) # матрица Вандермонда 3x3

Функции формирования числовых диапазонов

Следующая группа
функций, которые мы рассмотрим на этом занятии, служит для формирования
числовых диапазонов. Что делают эти функции? Когда мы с вами изучали язык Python, то говорили о
функции

range(Start, Stop, Step)

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

Название

Описание

arange()

Возвращает
одномерный массив с равномерно разнесенными числами указанного диапазона.

linspace(start,
stop, …)

Возвращает
одномерный массивcравномерно разнесенными числами, используя только
значения начала и конца интервала.

logspace(start,
stop, …)

Возвращает
одномерный массив с числами, равномерно распределенных по логарифмической
шкале.

geomspace(start,
stop, …)

Формирование
чисел по геометрической прогрессии.

meshgrid(x1,
…, xn, …)

x1,
…, xn – одномерные последовательности или массивы, используемые для
формирования координатной сетки по каждой из осей.

mgrid[]

Возвращает
массив плотных координатных сеток.

ogrid[]

Возвращает
открытую сетку значений.

Давайте
рассмотрим некоторые из них. Первая функция arrange довольно часто
применяется в программах на Python. Она позволяет проходить
заданный интервал с указанным шагом, например, так:

np.arange(5)# интервал [0; 5) с шагом 1
np.arange(1, 5)# интервал [1; 5) с шагом 1
np.arange(1, 5, 0.5) # интервал [1; 5) с шагом 0,5

Обратите
внимание, в отличие от функции range языка Python в arrange пакета NumPy можно указывать
вещественные значения. Вот еще один пример, демонстрирующий это:

Здесь все
величины вещественные. Мы начинаем движение от значения 0 с шагом 0,1 пока не
дойдем до значения пи (не включая его). И, далее, используя этот массив, можно
вычислить синус или косинус от всех этих значений:

np.cos(np.arange(0, np.pi, 0.1))

Видите, как это
удобно. Без пакета NumPyнам пришлось бы писать цикл и делать
вычисление для каждого значения аргумента. А здесь мы сразу получаем готовый
массив значений функции косинуса. Это работает гораздо быстрее циклов в Python.

Похожим образом
работает и функция linspace. Она разбивает указанный интервал на равномерные
отрезки и возвращает массив этих значений:

Мы указываем в
качестве аргументов интервал [start; stop] и число
отметок в этом интервале n. Если n = 0, то получим
пустой массив. При n = 1 – значение start. При n = 2 – значения start и stop. При n> 2
равномерное разбиение интервала точками m = n-2. Например:

np.linspace(0, np.pi, 0) # пустой массив
np.linspace(0, np.pi, 1) # одно значение 0
np.linspace(0, np.pi, 2) # два значения: 0 и pi
np.linspace(0, np.pi, 3) # три значения: 0, pi/2, pi

В чем отличие linspace от arange? В arange мы указываем
сами шаг движения по числовой оси. При этом число значений определяется
граничными значениями. А в linspace мы задаем граничные значения и
число делений, а шаг вычисляется автоматически.

Функции logspace
и geomspace работают аналогичным образом. У них указываются граничные значения
и число членов, а на выходе имеем массив из соответствующих величин. Например:

np.logspace(0, 1, 3) # значения: 1, sqrt(10), 10
np.logspace(0, 1, 4) # значения: 1, 2.15, 4.64, 10
 
np.geomspace(1, 4, 3) # значения: 1, 2, 4
np.geomspace(1, 16, 5) # значения: 1, 2, 4, 8, 16

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

Функции формирования массивов на основе данных

Рассмотрим
следующую группу, связанную с формированием на основе уже имеющихся данных.

Название

Описание

array(object,
…)

Преобразует
список или кортеж object в массив NumPy.

asanyarray(list,
…)

Преобразует
список list в массив array, сохраняя тип
подкласса.

ascontiguousarray(list,
…)

Возвращает
непрерывный массив в памяти, подобно как это организовано в языке C.

asmatrix(list,
…)

Преобразует
входную последовательность list в матрицу NumPy (тип matrix).

copy(list,
…)

Возвращает
копию массива list (если это объект NumPy) или просто
создает массив на основе списка языка Python.

frombuffer(buffer,
…)

Преобразует
данные из буфера в массив NumPy

fromfile(file,
…)

Возвращает
массив из данных текстового или бинарного файла file.

fromfunction(func,
shape, …)

Создает
массивразмерностью shape с помощью функции func.

fromiter(iter,
…)

Создает
массив на основе итерируемого объекта.

fromstring(string,
…)

Создает
массив из данных строки.

loadtxt(file,
…)

Формирует
массив из данных текстового файла.

Работа этих
функций вполне очевидна, рассмотрим только некоторые из них. Функция copy выполняет
копирование массива. Например, имеется массив:

a = np.array( [(1, 2), (3, 4)] )

И создать его
копию в памяти устройства, можно так:

В этом легко
убедиться, если вывести id этих объектов:

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

def getRange(x, y):
    return 100*x + y
 
a = np.fromfunction(getRange, (2, 2))
print(a)

Обратите
внимание, функция принимает два аргумента, т.к. формируется двумерная матрица
размерами 2×2. То есть,
число аргументов функции равно размерности матрицы и каждый аргумент
соответствует индексу по своей оси. При выполнении этой программы в консоли
увидим результат:

[[ 
0.   1.]

 [100. 101.]]

Отсюда хорошо
видно как менялись значения x, y при
формировании матрицы. При формировании первой строки x = 0, а yменялся от 0 до
1, при формировании второй строки: x = 1, yот 0 до 1.

Часто совместно
с fromfunction используют лямбда-функции в виде:

np.fromfunction(lambda x, y: x*100+y, (2, 2))

Результат будет
тем же.

Следующая
функция fromiter позволяет формировать массив на основе любого итерируемого
объекта. Например:

np.fromiter("hello", dtype='U1')

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

def getRange(N):
    for i in range(N):
        yield i
 
a = np.fromiter(getRange(4), dtype='int8')
print(a)

Здесь в качестве
объекта передается функция-генератор и на выходе получаем одномерный массив
чисел:

[0 1 2 3]

Последняя
функция, которую мы рассмотрим fromstring позволяет создавать массив из
строковых данных, например, так:

np.fromstring('1 2 3', dtype='int16', sep= ' ')

Здесь параметр sep определяет
разделитель между данными. Если числа следуют через запятую, то это явно нужно
указать в разделителе:

np.fromstring('1, 2, 3', dtype='int16', sep= ',')

Это
не все функции, с помощью которых можно формировать массивы в NumPy. Я отметил лишь
наиболее употребительные. Полный их список и подробное описание можно
посмотреть на официальном сайте:

https://numpy.org/doc/stable/

Видео по теме

  • Предыдущая
  • Следующая

Размер массива одинаковый, поэтому у вас не работало. Нужно было у индекса i остаток от деления проверять:

public static void main(String[] args) {
    int[] gamePanel = new int[400];

    for (int i = 0; i < gamePanel.length; i++) {
        if (i % 20 == 0)
            System.out.println();

        System.out.print(gamePanel[i] + " ");
    }

    System.out.println();
}

Можно немного поиграться, используя java8 stream:

public static void main(String[] args) {
    int[] gamePanel = new int[400];
    final int chunk = 20;

    for (int i = 0; i < gamePanel.length; i += chunk) {
        int[] subArr = Arrays.copyOfRange(gamePanel, i, i + chunk);
        String result = Arrays.stream(subArr)
                .mapToObj(String::valueOf)
                .collect(Collectors.joining(" "));

        System.out.println(result);
    }
}

PS.

if (i != 0 && i % 20 == 0) — более точное условие, которое не даст вывести на новую строку сразу же, т.к. i % 20 == 0 -> True

На уроке рассматриваются алгоритмы работы с двумерными массивами в Python: создание матрицы, инициализация элементов, вывод, обработка элементов матрицы

Создание, вывод и ввод матрицы в Питоне

    Для работы с матрицами в Python также используются списки. Каждый элемент списка-матрицы содержит вложенный список.

  • Таким образом, получается структура из вложенных списков, количество которых определяет количество строк матрицы, а число элементов внутри каждого вложенного списка указывает на количество столбцов в исходной матрице.
  • Рассмотрим пример матрицы размера 4 х 3:

    matrix = [[-1, 0, 1], 
        [-1, 0, 1], 
        [0, 1, -1],
        [1, 1, -1]]

    Данный оператор можно записать в одну строку:

    matrix = [[-1, 0, 1], [-1, 0, 1], [0, 1, -1], [1, 1, -1]]
  • Вывод матрицы можно осуществить одним оператором, но такой простой способ не позволяет выполнять какой-то предварительной обработки элементов:

Результат:
 

вывод матрицы

  • Для вывода матрицы в виде таблицы можно использовать специально заготовленную для этого процедуру:
    1. способ:
    2. 1
      2
      3
      4
      5
      
      def printMatrix ( matrix ): 
         for i in range ( len(matrix) ): 
            for j in range ( len(matrix[i]) ): 
                print ( "{:4d}".format(matrix[i][j]), end = "" ) 
            print ()

      В примере i – это номер строки, а j – номер столбца;
      len(matrix) – число строк в матрице.

    3. способ:
    4. 1
      2
      3
      4
      5
      
      def printMatrix ( matrix ): 
         for row in matrix: 
            for x in row: 
                print ( "{:4d}".format(x), end = "" ) 
            print ()

      Внешний цикл проходит по строкам матрицы (row), а внутренний цикл проходит по элементам каждой строки (x).

  • Для инициализации элементов матрицы случайными числами используется алгоритм:
  • 1
    2
    3
    4
    
    from random import randint
    n, m = 3, 3
    a = [[randint(1, 10) for j in range(m)] for i in range(n)]
    print(a)

    Обработка элементов двумерного массива

    Нумерация элементов двумерного массива, как и элементов одномерного массива, начинается с нуля.
    Т.е. matrix[2][3] — это элемент третьей строки четвертого столбца.

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

    ✍ Решение:
     

    1
    2
    3
    4
    5
    
    p = 1 
    for i in range(N): 
        for j in range(M): 
           p *= matrix[i][j] 
    print (p)

    Пример:
    Найти сумму элементов двумерного массива.

    ✍ Решение:
     

    Более подходящий вариант для Python:

    1
    2
    3
    4
    
    s = 0 
    for row in matrix: 
       s += sum(row) 
    print (s)

    Для поиска суммы существует стандартная функция sum.

    Задание Python 8_0:
    Получены значения температуры воздуха за 4 дня с трех метеостанций, расположенных в разных регионах страны:

    Номер станции 1-й день 2-й день 3-й день 4-й день
    1 -8 -14 -19 -18
    2 25 28 26 20
    3 11 18 20 25

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

    t[0][0]=-8 t[0][1]=-14 t[0][2]=-19 t[0][3]=-18
    t[1][0]=25 t[1][1]=28 t[1][2]=26 t[1][3]=20
    t[2][0]=11 t[2][1]=18 t[2][2]=20 t[2][3]=25
    1. Распечатать температуру на 2-й метеостанции за 4-й день и на 3-й метеостанции за 1-й день.
    2. Распечатать показания термометров всех метеостанций за 2-й день.
    3. Определить среднюю температуру на 3-й метеостанции.
    4. Распечатать, в какие дни и на каких метеостанциях температура была в диапазоне 24-26 градусов тепла.

    Задание Python 8_1:
    Написать программу поиска минимального и максимального элементов матрицы и их индексов.

    Задание Python 8_2:
    Написать программу, выводящую на экран строку матрицы, сумма элементов которой максимальна.

  • Для обработки элементов квадратной матрицы (размером N x N):
  • Для элементов главной диагонали достаточно использовать один цикл:
  • for i in range(N): 
       # работаем с matrix[i][i]
  • Для элементов побочной диагонали:
  • for i in range(N): 
       # работаем с matrix[i][N-1-i]

    Пример:Переставить 2-й и 4-й столбцы матрицы. Использовать два способа.

    ✍ Решение:
     

    1. for i in range(N): 
        c = A[i][2] 
        A[i][2] = A[i][4] 
        A[i][4] = c
    2. for i in range(N): 
        A[i][2], A[i][4] = A[i][4], A[i][2]

    Задание Python 8_3:
    Составить программу, позволяющую с помощью датчика случайных чисел сформировать матрицу размерностью N. Определить:

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

    • NumPy: матрицы и операции над ними
    • 1. Создание матриц
    • 2. Индексирование
    • 3. Векторы, вектор-строки и вектор-столбцы
    • 4. Datatypes
    • 5. Математические операции
    • 6. Умножение матриц и столбцов
    • 7. Объединение массивов
      • Задания: (Блок 1)
        • Задание 1:
        • Задание 2:
    • 8. Транспонирование матриц
    • 9. Определитель матрицы
    • 10. Ранг матрицы
    • 11. Системы линейных уравнений
    • 12. Обращение матриц
    • 13. Собственные числа и собственные вектора матрицы
    • 14. Расстояния между векторами
      • p-норма
      • 1 норма
      • 2 норма
    • 15. Расстояния между векторами
    • 16. Скалярное произведение и угол между векторами
    • 17. Комплексные числа в питоне
      • Задания: (Блок 2)
        • Задание 3:

    NumPy: матрицы и операции над ними

    Ссылка на jupyter notebook

    В этом ноутбуке из сторонних библиотек нам понадобится только NumPy.
    Для удобства импортируем ее под более коротким именем:

    import numpy as np
    

    1. Создание матриц

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

    Самый простой способ — с помощью функции
    numpy.array(list, dtype=None, …).

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

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

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

    a = np.array([1, 2, 3])   # Создаем одномерный массив
    print(type(a))            # Prints "<class 'numpy.ndarray'>"
    print(a.shape)            # Prints "(3,)" - кортеж с размерностями
    print(a[0], a[1], a[2])   # Prints "1 2 3"
    a[0] = 5                  # Изменяем значение элемента массива
    print(a)                  # Prints "[5, 2, 3]"
    
    b = np.array([[1,2,3],[4,5,6]])    # Создаем двухмерный массив
    print(b.shape)                     # Prints "(2, 3)"
    print(b[0, 0], b[0, 1], b[1, 0])   # Prints "1 2 4"
    print(np.arange(1, 5)) #Cоздает вектор с эелементами от 1 до 4
    
    <class 'numpy.ndarray'>
    (3,)
    1 2 3
    [5 2 3]
    (2, 3)
    1 2 4
    [1 2 3 4]
    
    matrix = np.array([[1, 2, 3], [2, 5, 6], [6, 7, 4]])
    print ("Матрица:n", matrix)
    
    Матрица:
     [[1 2 3]
     [2 5 6]
     [6 7 4]]
    

    Второй способ создания — с помощью встроенных функций
    numpy.eye(N, M=None, …), numpy.zeros(shape, …),
    numpy.ones(shape, …).

    Первая функция создает единичную матрицу размера N×M;
    если M не задан, то M = N.

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

    Примеры:

    b = np.eye(5)
    print ("Единичная матрица:n", b)
    
    Единичная матрица:
     [[1. 0. 0. 0. 0.]
     [0. 1. 0. 0. 0.]
     [0. 0. 1. 0. 0.]
     [0. 0. 0. 1. 0.]
     [0. 0. 0. 0. 1.]]
    
    c = np.ones((7, 5))
    print ("Матрица, состоящая из одних единиц:n", c)
    
    Матрица, состоящая из одних единиц:
     [[1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1.]
     [1. 1. 1. 1. 1.]]
    
    d = np.full((2,2), 7)  # Создает матрицу (1, 2) заполненую заданным значением
    print(d)               # Prints "[[ 7.  7.]
                           #          [ 7.  7.]]"
    
    e = np.random.random((2,2))  # Создает еденичную матрицу (2, 2) заполненую случаными числами (0, 1)
    print(e)                     # Might print "[[ 0.91940167  0.08143941]
                                 #               [ 0.68744134  0.87236687]]"
    
    [[7 7]
     [7 7]]
    [[0.25744383 0.48056466]
     [0.13767881 0.40578168]]
    

    Обратите внимание: размерность массива задается не двумя аргументами
    функции, а одним — кортежем!

    Вот так — np.ones(7, 5) — создать массив не получится, так как
    функции в качестве параметра shape передается 7, а не кортеж
    (7, 5).

    И, наконец, третий способ — с помощью функции
    numpy.arange([start, ]stop, [step, ], …), которая создает
    одномерный массив последовательных чисел из промежутка
    [start, stop) с заданным шагом step, и метода
    array.reshape(shape).

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

    v = np.arange(0, 24, 2)
    print ("Вектор-столбец:n", v)
    
    Вектор-столбец:
     [ 0  2  4  6  8 10 12 14 16 18 20 22]
    
    d = v.reshape((3, 4))
    print ("Матрица:n", d)
    
    Матрица:
     [[ 0  2  4  6]
     [ 8 10 12 14]
     [16 18 20 22]]
    

    Более подробно о том, как создавать массивы в NumPy, см.
    документацию.

    2. Индексирование

    Для получения элементов матрицы можно использовать несколько способов.
    Рассмотрим самые простые из них.

    Для удобства напомним, как выглядит матрица d:

    print ("Матрица:n", d)
    
    Матрица:
     [[ 0  2  4  6]
     [ 8 10 12 14]
     [16 18 20 22]]
    

    Элемент на пересечении строки i и столбца j можно
    получить с помощью выражения array[i, j].

    Обратите внимание: строки и столбцы нумеруются с нуля!

    print ("Второй элемент третьей строки матрицы:", d[2, 1])
    
    Второй элемент третьей строки матрицы: 18
    

    Из матрицы можно получать целые строки или столбцы с помощью выражений
    array[i, :] или array[:, j] соответственно:

    print ("Вторая строка матрицы d:n", d[1, :])
    print ("Четвертый столбец матрицы d:n", d[:, 3])
    
    Вторая строка матрицы d:
     [ 8 10 12 14]
    Четвертый столбец матрицы d:
     [ 6 14 22]
    

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

    print ("Элементы матрицы d с координатами (1, 2) и (0, 3):n", d[[1, 0], [2, 3]])
    
    Элементы матрицы d с координатами (1, 2) и (0, 3):
     [12  6]
    
    # Slicing
    
    # Создадим матрицу (3, 4)
    # [[ 1  2  3  4]
    #  [ 5  6  7  8]
    #  [ 9 10 11 12]]
    a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
    
    # Используя слайсинг, созадим матрицу b из элементов матрицы а
    # будем использовать 0 и 1 строку, а так же 1 и 2 столебц
    # [[2 3]
    #  [6 7]]
    b = a[:2, 1:3]
    print(b)
    
    # ОБРАТИТЕ ВНИМАНИЕ НА ИЗМЕНЕНИЕ ИСХОДОЙ МАТРИЦЫ
    print(a[0, 1])   # Prints "2"
    b[0, 0] = 77     # b[0, 0] is the same piece of data as a[0, 1]
    print(a[0, 1])   # Prints "77"
    
    [[2 3]
     [6 7]]
    2
    77
    
    # Integer array indexing
    
    a = np.array([[1,2], [3, 4], [5, 6]])
    print(a)
    print()
    
    # Пример Integer array indexing
    # В результате получится массив размерности (3,)
    # Обратите внимание, что до запятой идут индексы строк, после - столбцов
    print(a[[0, 1, 2], [0, 1, 0]])  # Prints "[1 4 5]"
    print()
    
    # По-другому пример можно записать так
    print(np.array([a[0, 0], a[1, 1], a[2, 0]]))  # Prints "[1 4 5]"
    
    [[1 2]
     [3 4]
     [5 6]]
    
    [1 4 5]
    
    [1 4 5]
    

    Примеры использования слайсинга:

    # Создадим новый маассив, из которого будем выбирать эллементы
    a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
    
    print(a)  # prints "array([[ 1,  2,  3],
              #                [ 4,  5,  6],
              #                [ 7,  8,  9],
              #                [10, 11, 12]])"
    
    # Создадим массив индексов
    b = np.array([0, 2, 0, 1])
    
    # Выберем из каждой строки элемент с индексом из b (индекс столбца берется из b)
    print(a[np.arange(4), b])  # Prints "[ 1  6  7 11]"
    print()
    
    # Добавим к этим элементам 10
    a[np.arange(4), b] += 10
    
    print(a)  # prints "array([[11,  2,  3],
              #                [ 4,  5, 16],
              #                [17,  8,  9],
              #                [10, 21, 12]])
    
    [[ 1  2  3]
     [ 4  5  6]
     [ 7  8  9]
     [10 11 12]]
    [ 1  6  7 11]
    
    [[11  2  3]
     [ 4  5 16]
     [17  8  9]
     [10 21 12]]
    
    a = np.array([[1,2], [3, 4], [5, 6]])
    
    bool_idx = (a > 2)   # Найдем эллементы матрицы a, которые больше 2
                         # В результате получим матрицу b, такой же размерности, как и a
    
    print(bool_idx)      # Prints "[[False False]
    print()              #          [ True  True]
                         #          [ True  True]]"
    
    # Воспользуемся полученным массивом для создания нового массива, ранга 1
    print(a[bool_idx])  # Prints "[3 4 5 6]"
    
    # Аналогично
    print(a[a > 2])     # Prints "[3 4 5 6]"
    
    [[False False]
     [ True  True]
     [ True  True]]
    
    [3 4 5 6]
    [3 4 5 6]
    
    #Помните, что вы можете пользоваться сразу несколькими типами индексирования
    a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
    
    row_r1 = a[1, :]
    row_r2 = a[1:2, :]
    print(row_r1, row_r1.shape)  # Prints "[5 6 7 8] (4,)"
    print(row_r2, row_r2.shape)  # Prints "[[5 6 7 8]] (1, 4)"
    
    [5 6 7 8] (4,)
    [[5 6 7 8]] (1, 4)
    

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

    3. Векторы, вектор-строки и вектор-столбцы

    Следующие два способа задания массива кажутся одинаковыми:

    a = np.array([1, 2, 3])
    b = np.array([[1], [2], [3]])
    

    Однако, на самом деле, это задание одномерного массива (то есть
    вектора) и двумерного массива:

    print ("Вектор:n", a)
    print ("Его размерность:n", a.shape)
    print ("Двумерный массив:n", b)
    print ("Его размерность:n", b.shape)
    
    Вектор:
     [1 2 3]
    Его размерность:
     (3,)
    Двумерный массив:
     [[1]
     [2]
     [3]]
    Его размерность:
     (3, 1)
    

    Обратите внимание: вектор (одномерный массив) и вектор-столбец
    или вектор-строка (двумерные массивы) являются различными объектами в
    NumPy, хотя математически задают один и тот же объект. В случае
    одномерного массива кортеж shape состоит из одного числа и имеет
    вид (n,), где n — длина вектора. В случае двумерных
    векторов в shape присутствует еще одна размерность, равная
    единице.

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

    a = a.T
    b = b.T
    
    print ("Вектор не изменился:n", a)
    print ("Его размерность также не изменилась:n", a.shape)
    print ("Транспонированный двумерный массив:n", b)
    print ("Его размерность изменилась:n", b.shape)
    
    Вектор не изменился:
     [1 2 3]
    Его размерность также не изменилась:
     (3,)
    Транспонированный двумерный массив:
     [[1 2 3]]
    Его размерность изменилась:
     (1, 3)
    

    4. Datatypes

    Все элементы в массиве numpy принадлежат одному типу. В этом плане
    массивы ближе к C, чем к привычным вам листам питона. Numpy имеет
    множество встренных типов, подходящих для решения большинства задач.

    x = np.array([1, 2])   # Автоматический выбор типа
    print(x.dtype)         # Prints "int64"
    
    x = np.array([1.0, 2.0])   # Автоматический выбор типа
    print(x.dtype)             # Prints "float64"
    
    x = np.array([1, 2], dtype=np.int64)   # Принудительное выставление типа
    print(x.dtype)                         # Prints "int64"
    
    int32
    float64
    int64
    

    5. Математические операции

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

    x = np.array([[1,2],[3,4]], dtype=np.float64)
    y = np.array([[5,6],[7,8]], dtype=np.float64)
    arr = np.array([1, 2])
    
    # Сложение происходит поэлеметно
    
    # [[ 6.0  8.0]
    #  [10.0 12.0]]
    print(x + y)
    print()
    print(np.add(x, y))
    print('С числом')
    print(x + 1)
    print('C массивом другой размерности')
    print(x + arr)
    
    [[ 6.  8.]
     [10. 12.]]
    
    [[ 6.  8.]
     [10. 12.]]
    С числом
    [[2. 3.]
     [4. 5.]]
    C массивом другой размерности
    [[2. 4.]
     [4. 6.]]
    
    # Вычитание
    print(x - y)
    print(np.subtract(x, y))
    
    [[-4. -4.]
     [-4. -4.]]
    [[-4. -4.]
     [-4. -4.]]
    
    # Деление
    # [[ 0.2         0.33333333]
    #  [ 0.42857143  0.5       ]]
    print(x / y)
    print(np.divide(x, y))
    
    [[0.2        0.33333333]
     [0.42857143 0.5       ]]
    [[0.2        0.33333333]
     [0.42857143 0.5       ]]
    
    # Другие функции
    # [[ 1.          1.41421356]
    #  [ 1.73205081  2.        ]]
    print(np.sqrt(x))
    
    [[1.         1.41421356]
     [1.73205081 2.        ]]
    

    6. Умножение матриц и столбцов

    Напоминание теории. Операция умножения определена для двух
    матриц, таких что число столбцов первой равно числу строк второй.

    Пусть матрицы A и B таковы, что
    A ∈ ℝn×k и
    B ∈ ℝk×m. Произведением матриц
    A и B называется матрица C, такая что
    cij = kr = 1airbrj, где cij
    элемент матрицы C, стоящий на пересечении строки с номером
    i и столбца с номером j.

    В NumPy произведение матриц вычисляется с помощью функции
    numpy.dot(a, b, …) или с помощью метода
    array1.dot(array2), где array1 и array2
    перемножаемые матрицы.

    a = np.array([[1, 0], [0, 1]])
    b = np.array([[4, 1], [2, 2]])
    r1 = np.dot(a, b)
    r2 = a.dot(b)
    
    print ("Матрица A:n", a)
    print ("Матрица B:n", b)
    print ("Результат умножения функцией:n", r1)
    print ("Результат умножения методом:n", r2)
    
    Матрица A:
     [[1 0]
     [0 1]]
    Матрица B:
     [[4 1]
     [2 2]]
    Результат умножения функцией:
     [[4 1]
     [2 2]]
    Результат умножения методом:
     [[4 1]
     [2 2]]
    

    Матрицы в NumPy можно умножать и на векторы:

    c = np.array([1, 2])
    r3 = b.dot(c)
    
    print ("Матрица:n", b)
    print ("Вектор:n", c)
    print ("Результат умножения:n", r3)
    
    Матрица:
     [[4 1]
     [2 2]]
    Вектор:
     [1 2]
    Результат умножения:
     [6 6]
    

    Обратите внимание: операция * производит над матрицами
    покоординатное умножение, а не матричное!

    r = a * b
    
    print ("Матрица A:n", a)
    print ("Матрица B:n", b)
    print ("Результат покоординатного умножения через операцию умножения:n", r)
    
    Матрица A:
     [[1 0]
     [0 1]]
    Матрица B:
     [[4 1]
     [2 2]]
    Результат покоординатного умножения через операцию умножения:
     [[4 0]
     [0 2]]
    

    Более подробно о матричном умножении в NumPy см.
    документацию.

    7. Объединение массивов

    Массивы можно Объединенять. Есть горизонтальное и вертикальное
    объединение.

    a = np.floor(10*np.random.random((2,2)))
    b = np.floor(10*np.random.random((2,2)))
    
    print(a)
    print(b)
    print()
    
    
    print(np.vstack((a,b)))
    print()
    
    print(np.hstack((a,b)))
    
    [[4. 0.]
     [1. 4.]]
    [[9. 7.]
     [2. 6.]]
    
    [[4. 0.]
     [1. 4.]
     [9. 7.]
     [2. 6.]]
    
    [[4. 0. 9. 7.]
     [1. 4. 2. 6.]]
    

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

    a = np.array(range(10), float)
    print(a)
    print()
    
    # Превратим в матрицу
    a = a.reshape((5, 2))
    print(a)
    print()
    
    # Вернем обратно
    print(a.flatten())
    
    # Другой вариант
    print(a.reshape((-1)))
    # Превратим в марицу (9, 1)
    print(a.reshape((-1, 1)))
    # Превратим в марицу (1, 9)
    print(a.reshape((1, -1)))
    
    [0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
    
    [[0. 1.]
     [2. 3.]
     [4. 5.]
     [6. 7.]
     [8. 9.]]
    
    [0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
    [0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
    [[0.]
     [1.]
     [2.]
     [3.]
     [4.]
     [5.]
     [6.]
     [7.]
     [8.]
     [9.]]
    [[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]]
    

    Задания: (Блок 1)

    Задание 1:

    Решите без использования циклов средставми NumPy (каждый пункт решается
    в 1-2 строчки)

    1. Создайте вектор с элементами от 12 до 42
    2. Создайте вектор из нулей длины 12, но его пятый елемент должен быть равен 1
    3. Создайте матрицу (3, 3), заполненую от 0 до 8
    4. Найдите все положительные числа в np.array([1,2,0,0,4,0])
    5. Умножьте матрицу размерности (5, 3) на (3, 2)
    6. Создайте матрицу (10, 10) так, чтобы на границе были 0, а внтури 1
    7. Создайте рандомный вектор и отсортируйте его
    8. Каков эквивалент функции enumerate для numpy массивов?
    9. *Создайте рандомный вектор и выполните нормализацию столбцов (из каждого столбца вычесть среднее этого столбца, из каждого столбца вычесть sd этого столбца)
    10. *Для заданного числа найдите ближайший к нему элемент в векторе
    11. *Найдите N наибольших значений в векторе
    # ваш код здесь
    

    Задание 2:

    Напишите полностью векторизованный вариант

    Дан трёхмерный массив, содержащий изображение, размера (height, width,
    numChannels), а также вектор длины numChannels. Сложить каналы
    изображения с указанными весами, и вернуть результат в виде матрицы
    размера (height, width). Считать реальное изображение можно при помощи
    функции

    scipy.misc.imread

    (если изображение не в формате png,
    установите пакет pillow:

    conda install pillow

    ). Преобразуйте
    цветное изображение в оттенки серого, использовав коэффициенты
    np.array([0.299, 0.587, 0.114]).

    # ваш код здесь
    

    8. Транспонирование матриц

    Напоминание теории. Транспонированной матрицей AT
    называется матрица, полученная из исходной матрицы A заменой
    строк на столбцы. Формально: элементы матрицы AT определяются
    как aTij = aji, где aTij — элемент
    матрицы AT, стоящий на пересечении строки с номером i
    и столбца с номером j.

    В NumPy транспонированная матрица вычисляется с помощью функции
    numpy.transpose() или с помощью метода array.T, где
    array — нужный двумерный массив.

    a = np.array([[1, 2], [3, 4]])
    b = np.transpose(a)
    c = a.T
    
    print ("Матрица:n", a)
    print ("Транспонирование функцией:n", b)
    print ("Транспонирование методом:n",  c)
    
    Матрица:
     [[1 2]
     [3 4]]
    Транспонирование функцией:
     [[1 3]
     [2 4]]
    Транспонирование методом:
     [[1 3]
     [2 4]]
    

    См. более подробно о
    numpy.transpose()
    и
    array.T
    в NumPy.

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

    9. Определитель матрицы

    Напоминание теории. Для квадратных матриц существует понятие
    определителя.

    Пусть A — квадратная матрица. Определителем (или
    детерминантом) матрицы A ∈ ℝn×n назовем
    число

    detA = α1, α2, …, αn( − 1)N(α1, α2, …, αn)aα11⋅⋅⋅aαnn, 

    где α1, α2, …, αn — перестановка
    чисел от 1 до n,
    N(α1, α2, …, αn) — число инверсий в
    перестановке, суммирование ведется по всем возможным перестановкам длины
    n.

    Не стоит расстраиваться, если это определение понятно не до конца — в
    дальнейшем в таком виде оно не понадобится.

    Например, для матрицы размера 2×2 получается:

    det

    a11


    a12











    a21


    a22


     = a11a22 − a12a21

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

    В NumPy определитель матрицы вычисляется с помощью функции
    numpy.linalg.det(a), где a — исходная матрица.

    a = np.array([[1, 2, 1], [1, 1, 4], [2, 3, 6]], dtype=np.float32)
    det = np.linalg.det(a)
    
    print ("Матрица:n", a)
    print ("Определитель:n", det)
    
    Матрица:
     [[1. 2. 1.]
     [1. 1. 4.]
     [2. 3. 6.]]
    Определитель:
     -1.0
    

    Рассмотрим одно интересное свойство определителя. Пусть у нас есть
    параллелограмм с углами в точках
    (0, 0), (c, d), (a + c, b + d), (a, b) (углы даны в порядке обхода по
    часовой стрелке). Тогда площадь этого параллелограмма можно вычислить
    как модуль определителя матрицы


    a


    c











    b


    d


    .
    Похожим образом можно выразить и объем параллелепипеда через
    определитель матрицы размера 3×3.

    10. Ранг матрицы

    Напоминание теории. Рангом матрицы A называется
    максимальное число линейно независимых строк (столбцов) этой матрицы.

    В NumPy ранг матрицы вычисляется с помощью функции
    numpy.linalg.matrix_rank(M, tol=None), где M — матрица,
    tol — параметр, отвечающий за некоторую точность вычисления. В
    простом случае можно его не задавать, и функция сама определит
    подходящее значение этого параметра.

    a = np.array([[1, 2, 3], [1, 1, 1], [2, 2, 2]])
    r = np.linalg.matrix_rank(a)
    
    print ("Матрица:n", a)
    print ("Ранг матрицы:", r)
    
    Матрица:
     [[1 2 3]
     [1 1 1]
     [2 2 2]]
    Ранг матрицы: 2
    

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

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

    a = np.array([1, 2, 3])
    b = np.array([1, 1, 1])
    c = np.array([2, 3, 5])
    m = np.array([a, b, c])
    
    print (np.linalg.matrix_rank(m) == m.shape[0])
    
    True
    

    11. Системы линейных уравнений

    Напоминание теории. Системой линейных алгебраических уравнений
    называется система вида Ax = b, где
    A ∈ ℝn×m, x ∈ ℝm×1, b ∈ ℝn×1.
    В случае квадратной невырожденной матрицы A решение системы
    единственно.

    В NumPy решение такой системы можно найти с помощью функции
    numpy.linalg.solve(a, b), где первый аргумент — матрица
    A, второй — столбец b.

    a = np.array([[3, 1], [1, 2]])
    b = np.array([9, 8])
    x = np.linalg.solve(a, b)
    
    print ("Матрица A:n", a)
    print ("Вектор b:n", b)
    print ("Решение системы:n", x)
    
    Матрица A:
     [[3 1]
     [1 2]]
    Вектор b:
     [9 8]
    Решение системы:
     [2. 3.]
    

    Убедимся, что вектор x действительно является решением системы:

    print (a.dot(x))
    
    [9. 8.]
    

    Бывают случаи, когда решение системы не существует. Но хотелось бы все
    равно “решить” такую систему. Логичным кажется искать такой вектор
    x, который минимизирует выражение
    Ax − b2 — так мы приблизим выражение
    Ax к b.

    В NumPy такое псевдорешение можно искать с помощью функции
    numpy.linalg.lstsq(a, b, …), где первые два аргумента такие
    же, как и для функции numpy.linalg.solve(). Помимо решения
    функция возвращает еще три значения, которые нам сейчас не понадобятся.

    a = np.array([[0, 1], [1, 1], [2, 1], [3, 1]])
    b = np.array([-1, 0.2, 0.9, 2.1])
    x, res, r, s = np.linalg.lstsq(a, b, rcond=None)
    
    print ("Матрица A:n", a)
    print ("Вектор b:n", b)
    print ("Псевдорешение системы:n", x)
    
    Матрица A:
     [[0 1]
     [1 1]
     [2 1]
     [3 1]]
    Вектор b:
     [-1.   0.2  0.9  2.1]
    Псевдорешение системы:
     [ 1.   -0.95]
    

    12. Обращение матриц

    Напоминание теории. Для квадратных невырожденных матриц определено
    понятие обратной матрицы.

    Пусть A — квадратная невырожденная матрица. Матрица
    A − 1 называется обратной матрицей к A, если

    AA − 1 = A − 1A = I, 

    где I — единичная матрица.

    В NumPy обратные матрицы вычисляются с помощью функции
    numpy.linalg.inv(a), где a — исходная матрица.

    a = np.array([[1, 2, 1], [1, 1, 4], [2, 3, 6]], dtype=np.float32)
    b = np.linalg.inv(a)
    
    print ("Матрица A:n", a)
    print ("Обратная матрица к A:n", b)
    print ("Произведение A на обратную должна быть единичной:n", a.dot(b))
    
    Матрица A:
     [[1. 2. 1.]
     [1. 1. 4.]
     [2. 3. 6.]]
    Обратная матрица к A:
     [[ 6.  9. -7.]
     [-2. -4.  3.]
     [-1. -1.  1.]]
    Произведение A на обратную должна быть единичной:
     [[1. 0. 0.]
     [0. 1. 0.]
     [0. 0. 1.]]
    

    13. Собственные числа и собственные вектора матрицы

    Напоминание теории. Для квадратных матриц определены понятия
    собственного вектора и собственного числа.

    Пусть A — квадратная матрица и
    A ∈ ℝn×n. Собственным вектором матрицы
    A называется такой ненулевой вектор
    x ∈ ℝn, что для некоторого
    λ ∈ ℝ выполняется равенство
    Ax = λx. При этом λ называется
    собственным числом матрицы A. Собственные числа и
    собственные векторы матрицы играют важную роль в теории линейной алгебры
    и ее практических приложениях.

    В NumPy собственные числа и собственные векторы матрицы вычисляются
    с помощью функции numpy.linalg.eig(a), где a — исходная
    матрица. В качестве результата эта функция выдает одномерный массив
    w собственных чисел и двумерный массив v, в котором по
    столбцам записаны собственные вектора, так что вектор v[:, i]
    соотвествует собственному числу w[i].

    a = np.array([[-1, -6], [2, 6]])
    w, v = np.linalg.eig(a)
    
    print ("Матрица A:n", a)
    print ("Собственные числа:n", w)
    print ("Собственные векторы:n", v)
    
    Матрица A:
     [[-1 -6]
     [ 2  6]]
    Собственные числа:
     [2. 3.]
    Собственные векторы:
     [[-0.89442719  0.83205029]
     [ 0.4472136  -0.5547002 ]]
    

    Обратите внимание: у вещественной матрицы собственные значения или
    собственные векторы могут быть комплексными.

    14. Расстояния между векторами

    Вспомним некоторые нормы, которые можно ввести в пространстве
    n, и рассмотрим, с помощью каких библиотек и
    функций их можно вычислять в NumPy.

    p-норма

    p-норма (норма Гёльдера) для вектора
    x = (x1, …, xn) ∈ ℝn вычисляется по
    формуле:

    xp = (ni = 1|xi|p)1 ⁄ p,  p ≥ 1.

    В частных случаях при: * p = 1 получаем 1 норму
    * p = 2 получаем 2 норму

    Далее нам понабится модуль numpy.linalg, реализующий некоторые
    приложения линейной алгебры. Для вычисления различных норм мы используем
    функцию numpy.linalg.norm(x, ord=None, …), где x
    исходный вектор, ord — параметр, определяющий норму (мы
    рассмотрим два варианта его значений — 1 и 2). Импортируем эту функцию:

    from numpy.linalg import norm
    

    1 норма

    1 норма (также известная как манхэттенское
    расстояние)
    для вектора x = (x1, …, xn) ∈ ℝn
    вычисляется по формуле:

    x1 = ni = 1|xi|.

    Ей в функции numpy.linalg.norm(x, ord=None, …) соответствует
    параметр ord=1.

    a = np.array([1, 2, -3])
    print('Вектор a:', a)
    
    Вектор a: [ 1  2 -3]
    
    print('L1 норма вектора a:n', norm(a, ord=1))
    
    L1 норма вектора a:
     6.0
    

    2 норма

    2 норма (также известная как евклидова норма) для вектора
    x = (x1, …, xn) ∈ ℝn вычисляется по
    формуле:

    x2 = (ni = 1(xi)2).

    Ей в функции numpy.linalg.norm(x, ord=None, …) соответствует
    параметр ord=2.

    print ('L2 норма вектора a:n', norm(a, ord=2))
    
    L2 норма вектора a:
     3.7416573867739413
    

    Более подробно о том, какие еще нормы (в том числе матричные) можно
    вычислить, см.
    документацию.

    15. Расстояния между векторами

    Для двух векторов x = (x1, …, xn) ∈ ℝn и
    y = (y1, …, yn) ∈ ℝn 1 и
    2 раccтояния вычисляются по следующим формулам
    соответственно:

    ρ1(x, y) = x − y1 = ni = 1|xi − yi|

    ρ2(x, y) = x − y2 = (ni = 1(xi − yi)2).

    a = np.array([1, 2, -3])
    b = np.array([-4, 3, 8])
    print ('Вектор a:', a)
    print ('Вектор b:', b)
    
    Вектор a: [ 1  2 -3]
    Вектор b: [-4  3  8]
    
    print ('L1 расстояние между векторами a и b:n', norm(a - b, ord=1))
    print ('L2 расстояние между векторами a и b:n', norm(a - b, ord=2))
    
    L1 расстояние между векторами a и b:
     17.0
    L2 расстояние между векторами a и b:
     12.12435565298214
    

    16. Скалярное произведение и угол между векторами

    a = np.array([0, 5, -1])
    b = np.array([-4, 9, 3])
    print ('Вектор a:', a)
    print ('Вектор b:', b)
    
    Вектор a: [ 0  5 -1]
    Вектор b: [-4  9  3]
    

    Скалярное произведение в пространстве n для двух
    векторов x = (x1, …, xn) и
    y = (y1, …, yn) определяется как:

    x, y⟩ = ni = 1xiyi.

    Длиной вектора x = (x1, …, xn) ∈ ℝn
    называется квадратный корень из скалярного произведения, то есть длина
    равна евклидовой норме вектора:

    |x| = (x, x) = (ni = 1x2i) = x2.

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

    x, y⟩ = |x||y|cos(α) ⟹ cos(α) = (x, y)/(|x||y|), 

    где α ∈ [0, π] — угол между векторами x и
    y.

    cos_angle = np.dot(a, b) / norm(a) / norm(b)
    print ('Косинус угла между a и b:', cos_angle)
    print ('Сам угол:', np.arccos(cos_angle))
    
    Косинус угла между a и b: 0.8000362836474323
    Сам угол: 0.6434406336093618
    

    17. Комплексные числа в питоне

    Напоминание теории. Комплексными числами называются числа вида
    x + iy, где x и y — вещественные числа, а
    i — мнимая единица (величина, для которой выполняется равенство
    i2 =  − 1). Множество всех комплексных чисел обозначается
    буквой (подробнее про комплексные числа см.
    википедию).

    В питоне комплескные числа можно задать следующим образом (j
    обозначает мнимую единицу):

    a = 3 + 2j
    b = 1j
    
    print ("Комплексное число a:n", a)
    print ("Комплексное число b:n", b)
    
    Комплексное число a:
     (3+2j)
    Комплексное число b:
     1j
    

    С комплексными числами в питоне можно производить базовые арифметические
    операции так же, как и с вещественными числами:

    c = a * a
    d = a / (4 - 5j)
    
    print ("Комплексное число c:n", c)
    print ("Комплексное число d:n", d)
    
    Комплексное число c:
     (5+12j)
    Комплексное число d:
     (0.0487804878048781+0.5609756097560976j)
    

    Задания: (Блок 2)

    Задание 3:

    Рассмотрим сложную математическую функцию на отрезке [1, 15]:

    f(x) = sin(x / 5) * exp(x / 10) + 5 * exp(-x / 2)

    images/lab14/func.png

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

    Как известно, многочлен степени n (то есть w0 +
    w1x + w2x2 + + wnxn)
    однозначно определяется любыми n + 1 различными точками, через которые
    он проходит. Это значит, что его коэффициенты w0, … wn
    можно определить из следующей системы линейных уравнений:

    images/lab14/eqs.png

    где через x1, …, xn, xn + 1 обозначены точки, через которые
    проходит многочлен, а через f(x1), …, f(xn), f(xn + 1)
    значения, которые он должен принимать в этих точках.

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

    1. Сформируйте систему линейных уравнений (то есть задайте матрицу
      коэффициентов A и свободный вектор b) для многочлена первой степени,
      который должен совпадать с функцией f в точках 1 и 15. Решите данную
      систему с помощью функции scipy.linalg.solve. Нарисуйте функцию f и
      полученный многочлен. Хорошо ли он приближает исходную функцию?
    2. Повторите те же шаги для многочлена второй степени, который совпадает
      с функцией f в точках 1, 8 и 15. Улучшилось ли качество
      аппроксимации?
    3. Повторите те же шаги для многочлена третьей степени, который
      совпадает с функцией f в точках 1, 4, 10 и 15. Хорошо ли он
      аппроксимирует функцию? Коэффициенты данного многочлена (четыре числа
      в следующем порядке: w_0, w_1, w_2, w_3) являются ответом на задачу.
      Округлять коэффициенты не обязательно, но при желании можете
      произвести округление до второго знака (т.е. до числа вида 0.42)

    Понравилась статья? Поделить с друзьями:

    Не пропустите также:

  • Как найти финансового брокера
  • Как в лайке найти человека поблизости
  • Cup fan error как исправить
  • Секреты как быстро найти
  • Как найти число сторон многоугольника зная угол

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии