-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathintronumpy.tex
More file actions
3974 lines (3492 loc) · 168 KB
/
intronumpy.tex
File metadata and controls
3974 lines (3492 loc) · 168 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\chapter{Introducción a Numpy\\ Introduction to Numpy}\index{Numpy} \index[eng]{Numpy}\label{ch:numpy}
\chaptermark{Intro. a Numpy \textreferencemark\ Intro to Numpy}
\epigraph{When the going gets tough, the tough get going}{Popular Witticism (US)}
\begin{paracol}{2}
\section{Numpy: un paquete de Python para cálculo nu\-mérico}
\sectionmark{Numpy: módulo mat. \textreferencemark\ Numpy: a math. Pack.}
En el capítulo \ref{ch:intpr}, vimos cómo importar mó\-dulos de python en un script o directamente en el terminal de Ipython, de modo que podamos reutilizar el código contenido en ellos. Numpy es un librería de python que contiene funciones y variables específicamente diseñadas para el cálculo numérico. Está estructurada en forma de módulos y submódulos de modo que, para utilizarla en nuestros programas, basta con importarla en nuestros scripts, importar sus submódulos o importar sus funciones.
La base de Numpy la constituyen objetos y operaciones algebráicas. En esta sección vamos a repasar algunos conceptos fundamentales de álgebra lineal y cómo pueden manejarse empleando Python y la librería numpy. No daremos definiciones precisas ni tampoco demostraciones, ya que tanto unas como otras se verán en detalle en la asignatura de álgebra.
\paragraph{Matrices.} Desde un punto de vista funcional definiremos una matriz como una tabla bidimensional de números ordenados en filas y columnas,
\switchcolumn
\section{Numpy: a Python library for scientific computing}
\sectionmark{Numpy: módulo mat. \textreferencemark\ Numpy: a math. Pack.}
In chapter \ref{ch:intpr}, we have seen how to import Python modules to a script or the Ipython console. In this way, we can reuse the code available in the modules. Numpy is a Python library with functions and variables specifically intended to perform scientific computing. Numpy is structured in modules and submodules so that we can import the whole library, its submodules, or just any of its functions into our scripts. The background of Numpy is built of algebraic objects and operations. In this section, we will review some fundamental notions of linear algebra and how to deal with them using Numpy. We will not provide formal definitions or demonstrations because both will be studied in detail in algebra during the next term.
\paragraph{Matrices} From a functional perspective, we will define a matrix as a table of numbers ordered by rows and columns,
\end{paracol}
\begin{equation*}
A=
\begin{pmatrix}
1& \sqrt{2}& 3.5& 0\\
-2& \pi& -4.6& 4\\
7& -19& 2.8& 0.6
\end{pmatrix}
\end{equation*}
\begin{paracol}{2}
Cada línea horizontal de números constituye una \emph{fila} de la matriz y cada línea vertical una \emph{columna} de la misma.
A una matriz con $m$ filas y $n$ columnas se la denomina matriz de orden $m\times n$. $m$ y $n$ son la dimensiones de la matriz y se dan siempre en el mismo orden: primero el número de filas y después el de columnas. Así, la matriz $A$ del ejemplo anterior es una matriz $3\times 4$, y como esta formada por números reales se dice que $A\in\mathbb{R}^{3\times 4}$. El orden de una matriz expresa el tamaño de la matriz.
Dos matrices son iguales si tienen el mismo orden, y los elementos que ocupan en ambas matrices los mismo lugares son iguales.
Una matriz es cuadrada, si tiene el mismo número de filas que de columnas. Es decir es de orden $n\times n$.
Mientras no se diga expresamente lo contrario, emplearemos letras mayúsculas $A, B, \cdots$ para representar matrices. La expresión $A_{m\times n}$ indica que la matriz $A$ tiene dimensiones $m \times n$. Para denotar los elementos de una matriz, emplearemos la misma letra en minúsculas empleada para nombrar la matriz, indicando mediante subíndices, y siempre por este orden, la fila y la columna a la que pertenece el elemento. Así por ejemplo $a_{ij}$ representa al elemento de la matriz $A$, que ocupa la fila $i$ y la columna $j$.
\switchcolumn
Each horizontal line of numbers forms a matrix row, and each vertical line a matrix column.
A matrix with $m$ rows and $n$ columns is denoted as a matrix of order $m\times n$. $m$ and $n$ are the matrix dimensions, and they are always defined in the same order: first, the number of rows and then the number of columns. So matrix $A$ in the example above is a $3\times 4$ matrix, and as it is built of real numbers, we say that $A\in \mathbb{R}^{3\times 4}$. The matrix order defines the size of the matrix.
Two matrices are equal if they have the same order and the entries located in both matrices in the same place are equal. A matrix is square whenever it has the same number of rows and columns. That is, it is an $n\times n$ matrix.
From now on, we will use capital letters $A,\ B,\cdots$ to name matrices. The expression $A_{m\times n}$ means that matrix $A$ has dimensions $m\times n$. We will refer to the entries of a matrix using the same letter used to name the matrix but in lowercase and using subindexes to indicate the row and column the entry belongs to. The first subindex always represents the row, and the second is the column. For instance, $a_{ij}$ Represents the matrix $A$ entry that belongs to row $i$ and to column $j$.
\end{paracol}
\begin{equation*}
A=
\begin{pmatrix}
1& \sqrt{2}& 3.5& 0\\
-2& \pi& -4.6& 4\\
7& -19& 2.8& 0.6
\end{pmatrix}
\rightarrow a_{23}=-4.6
\end{equation*}
\begin{paracol}{2}
\paragraph{Vectores.}
A una matriz compuesta por una sola fila, la denominaremos vector fila. A una matriz compuesta por una sola columna la denominaremos vector columna. Siempre que hablemos de un vector, sin especificar más, entenderemos que se trata de un vector columna.\footnote{Esta identificación de los vectores como vectores columna no es general. La introducimos porque simplifica las explicaciones posteriores.} Para representar vectores, emplearemos letras minúsculas. Para representar sus elementos añadiremos a la letra que representa al vector un subíndice indicando la fila a la que pertenece el elemento.
\switchcolumn
We call a matrix formed by a single row a row vector. We call a matrix formed by a single column a column vector. Whenever we speak of a vector without further specification, we consider it a column vector.\footnote{This identification of a vector with a column vector is by no means general. We introduce it because it simplifies the exposition.}. To name vectors, we will use lowercase letters. To name the entries of a vector, we will add a subindex to the letter representing the vector to show the row the entry belongs to.
\end{paracol}
\begin{equation*}
a=
\begin{pmatrix}
a_1\\
a_2\\
\vdots \\
a_i\\
\vdots \\
a_n
\end{pmatrix}
\end{equation*}
\begin{paracol}{2}
Podemos asociar los puntos del plano con los vectores de dimensión dos. Para ello, usamos una representación cartesiana, en la que los elementos del vector son los valores de las coordenadas $(x,y)$ del punto del plano que representan. Cada vector se representa gráficamente mediante una flecha que parte del origen de coordenadas y termina en el punto $(x,y)$ representado por el vector. La figura \ref{fig:vectores} representa los vectores,
\switchcolumn
We can establish a relationship between the plane points and two-dimensional vectors. To do so, we use a Cartesian representation, in which the entries of a vector are the $(x,y)$ coordinates of the point of the plane they represent. Each vector is drawn using an arrow that starts at the origin of the coordinates and ends at the point $(x,y)$ represented by the vector. Figure \ref{fig:vectores} represents vectors,
\end{paracol}
\begin{equation*}
a=
\begin{pmatrix}
1\\
2
\end{pmatrix},
b=
\begin{pmatrix}
2\\
-3
\end{pmatrix},
c=
\begin{pmatrix}
0\\
-2
\end{pmatrix}
\end{equation*}
\begin{figure}[h]
\centering
\includegraphics[width=7cm]{vectores.eps}
\bicaption{Representación gráfica de vectores en el plano}{Graphic of vectors on the plane}
\label{fig:vectores}
\end{figure}
\begin{paracol}{2}
De modo análogo, podemos asociar vectores de dimensión tres con puntos en el espacio tridimensional. En este caso, los valores de los elementos del vector corresponden con la coordenadas $(x,y,z)$ de los puntos en el espacio. La figura \ref{fig:vectores3} muestra la representación gráfica en espacio tridimensional de los vectores,
\switchcolumn
Likewise, we can associate vectors of dimension three with points in the 3D space. In this case, the vector entries represent the coordinates $(x,y,z)$ of the points in the space. Figure \ref{fig:vectores3} shows a graphic representation of vectors,
\end{paracol}
\begin{equation*}
a=
\begin{pmatrix}
1\\
2\\
1
\end{pmatrix},
b=
\begin{pmatrix}
2\\
-3\\
-1
\end{pmatrix},
c=
\begin{pmatrix}
0\\
-2\\
1
\end{pmatrix}
\end{equation*}
\begin{figure}[h]
\centering
\includegraphics[width=9cm]{vectores3.eps}
\bicaption{Representación gráfica de vectores en el espacio 3D}{Graphic of vector in the 3D space}
\label{fig:vectores3}
\end{figure}
\begin{paracol}{2}
Evidentemente para vectores de mayor dimensión, no es posible obtener una representación gráfica. Si embargo muchas de las propiedades geométricas, observables en los vectores bi y tridimensionales, pueden extrapolarse a vectores de cualquier dimensión.
\subsection{Vectores y matrices en\\ Numpy.} \index{Vectores!en Numpy} \index{Matrices!en Numpy}
\paragraph{Matrices.} Una de las característica más interesantes de Numpy, es la posibilidad de crear fácilmente matrices. Se pueden crear de diferentes maneras, la más elemental de todas ellas, emplea la funcion de Numpy \mintinline{python}{array} aplicada a una lista de filas de la matriz que se quiere construir. Cada fila debe ser a su vez una lista de números. Evidentemente, para que se pueda construir la matriz, todas las filas deben tener el mismo número de elementos. El siguiente ejemplo muestra como construir una matriz de dos filas y tres columnas,
\switchcolumn
Obviously, it is impossible to get a graphic representation for vectors of larger dimensions. Nevertheless, many geometrical properties owned by 2D and 3D vectors can be applied to vectors of whatever dimension.
\subsection{Vectors and matrices in \\ Numpy.}\index[eng]{Vectors! in Numpy}\index[eng]{Matrices! in Numpy}
\paragraph{Matrices.} One interesting feature of numpy is that it allows us to create matrices easily. There are several methods to create them, but using the Numpy function \mintinline{python}{array} with a Python list with the rows of the matrix we want to build is probably the easiest method. Each row should be, in turn, a list of numbers, i.e., matrix entries. Of course, to build a matrix, all rows should have the same number of entries. The following example shows how to build a matrix of two rows and three columns.
\end{paracol}
\begin{center}
\begin{minipage}{0.4\textwidth}
\begin{minted}{python}
In [3]: import numpy as np
In [4]: A = np.array([[1,2,3],[4,5,6]])
In [5]: print(A)
[[1 2 3]
[4 5 6]]
In [6]: L = [[1,2,3],[4,5,6]]
In [7]: B = np.array(L)
In [9]: print(L)
[[1, 2, 3], [4, 5, 6]]
In [10]: print(B)
[[1 2 3]
[4 5 6]]
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
Lo primero que hacemos es importar Numpy, lo importamos usando como alias la abreviatura np, porque es más cómodo a la hora de llamar a funciones específicas de Numpy. Hemos construido dos matrices iguales \mintinline{python}{A} y \mintinline{python}{B}. En el primer caso hemos creado directamente dentro de la llamada a la función \mintinline{python}{array}, la lista a partir de la cual construimos la matriz. En el segundo caso, hemos construido primero una lista \mintinline{python}{L}, y luego hemos empleado dicha lista como variable de entrada de la función \mintinline{python}{array}. Si nos fijamos en las líneas [9] y [10], vemos como Python distingue la lista ---todos sus elementos aparacen representados en la misma línea---, de la matriz en la que cada fila ocupa una línea distinta. Podemos construir matrices a partir de listas y variables ya definidas, siempre que seamos coherentes con el criterio de que cada fila se cree a partir de una lista y que todas las filas tengan los mismos elementos,
\switchcolumn
First, we import Numpy; we do it using \mintinline{python}{np} as an alias. The reason is that \mintinline{python}{np} is shorter than \mintinline{python}{numpy}, and it eases the calls to specific Numpy functions. We have built two identical matrices \mintinline{python}{a} and \mintinline{python}{B}. In the first case, we have straightforwardly created the list needed to make the matrix inside the call to the function \mintinline{python}{array}. In the second case, we first created a list \mintinline{python}{L}, and then we used it as an input variable to the function \mintinline{python}{array}. Focusing on lines [9] and [10], we see how Python can tell a list and a matrix apart. For a list, Python represents all entries in the same line. For a matrix, each row is written in a different line.
We can build matrices from lists and variables already defined as long as we follow the criteria that each row be created from a list and all rows have the same number of entries,
\end{paracol}
\begin{center}
\begin{minipage}{0.4\textwidth}
\begin{minted}{python}
In [23]: a =1; b= 2; c =3
In [24]: d =[4,5,6]
\end{minted}
\end{minipage}
\end{center}
\begin{center}
\begin{minipage}{0.4\textwidth}
\begin{minted}{python}
In [25]: C = np.array([[a,b,c],d])
In [26]: print(C)
[[1 2 3]
[4 5 6]]
In [27]: C = np.array([[a,b,c],d,[7,8,9]])
In [28]: print(C)
[[1 2 3]
[4 5 6]
[7 8 9]]
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
\paragraph*{Indexación.} \index{Numpy!indexación}Al igual que se hace en álgebra, Numpy es capaz de referirse a un elemento cualquiera de una matriz empleando índices para determinar su posición (fila y columna) dentro de la matriz.
\switchcolumn
\paragraph{Indexing}\index[eng]{Numpy!Indexing} As in algebra, in Numpy is also possible to refer any entry of a matrix using indexes to indicate its position (row and column) in the matrix.
\end{paracol}
\begin{equation*}
A=
\begin{pmatrix}
a_{11}&a_{12}&a_{13}\\
a_{21}&a_{22}&a_{23}\\
a_{31}&a_{32}&a_{33}
\end{pmatrix}
\end{equation*}
\begin{paracol}{2}
Sin embargo, el criterio para referirse a un elemento concreto de una matriz, en Numpy está heredado de las listas: se indica el nombre de la variable que contiene la matriz y a continuación, entre corchetes y separados por una coma, el índice de su fila y después él de su columna \textbf{pero empezando a contar desde $0$}. Es decir, la primera fila de una matriz de dimensión $m\times n$ es la fila $0$ y la última es la fila $m-1$. De modo análogo su primera columna es la $0$ y su última columna es la $n-1$,
\switchcolumn
However, the Numpy criteria to refer to a specific entry inside a matrix has been borrowed from Python Lists: we write the name of the matrix followed by the row and column indexes of the entry we are interested in, enclosed in a square bracket and separated by a comma. The point is that we \textbf{count the rows and columns starting at $0$}. Thus, the first row of a matrix with dimensions $m\times n$ is the row $0$, and the last is the row $m-1$. Likewise, its first column is column $0$, and the last one is column $n-1$,
\end{paracol}
\begin{center}
\begin{minipage}{0.3\textwidth}
\begin{minted}{python}
In [31]: print(C)
[[1 2 3]
[4 5 6]
[7 8 9]]
In [32]: C[1,2]
Out[32]: 6
In [33]: C[0,0]
Out[33]: 1
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
Numpy puede seleccionar dentro de una matriz no solo elementos aislados, sino también submatrices completas.
Para ello, emplea un símbolo reservado, el símbolo \emph{dos puntos} $:$. Este símbolo se emplea para recorrer valores desde un valor inicial hasta un valor final, con un incremento o paso fijo. La sintaxis es: \mintinline{python}{inicio:fin:paso}. Es importante tener en cuenta que Numpy detendrá la cuenta en el valor \mintinline{python}{stop-step}. Además, si no indicamos el tamaño del paso, Numpy tomará por defecto un paso igual a uno. En este caso basta emplear \mintinline{python}{start:stop}
\switchcolumn
Inside a matrix, Numpy can select single entries and whole submatrices. To do so, it uses the colon : symbol as a special symbol. Using a fixed step, we use this symbol to cover a set of values from a start (initial) value to a stop (final) one. The syntax is simple: \mintinline{python}{start:stop:step}. Beware! Numpy will stop the count in the step \mintinline{python}{stop-step}. Besides, if we leave apart the step size, Numpy will take a step equal to one. In this case, the expression is just \mintinline{python}{start:stop}
\end{paracol}
\begin{center}
\begin{minted}{python}
In [87]: D = numpy.array([[1.,2.,3.],[4.,5.,6.],[-2,-3,0],[3,2,1]])
In [88]: print(D)
[[ 1. 2. 3.]
[ 4. 5. 6.]
[-2. -3. 0.]
[ 3. 2. 1.]]
In [90]: D[0:1,0:3]
Out[90]: array([[1., 2., 3.]])
In [91]: D[0:2,0:2]
Out[91]:
array([[1., 2.],
[4., 5.]])
In [92]: D[2:3,1:2]
Out[92]: array([[-3.]])
In [93]: D[3:4,0:3]
Out[93]: array([[3., 2., 1.]])
In [94]: D[0:4,0:3]
Out[94]:
array([[ 1., 2., 3.],
[ 4., 5., 6.],
[-2., -3., 0.],
[ 3., 2., 1.]])
In [95]: D[0:4,2:3]
Out[95]:
array([[3.],
[6.],
[0.],
[1.]])
\end{minted}
\end{center}
\begin{paracol}{2}
La línea [90], extrae un vector fila con los elementos de la primera fila de la matriz \mintinline{python}{D}. La fila [91] extrae una matriz de dimension $2\times 2$ con los cuatro elementos de la esquina superior izquierda de la matriz original. La fila [92] extrae un único elemento pero sigue siendo una matriz de dimensión $1 \times 1$, por tanto es distinto que si empleamos la indexación directa del elemento: \mintinline{python}{D[2,1]}. La línea [93] nos devuelve un vector fila con la última fila de la matriz. La línea [94], nos devuelve de nuevo la matriz entera. Por último la línea [95] nos devuelve un vector columna con la primera columna de la matriz.
Hemos dicho que la línea [95] nos devuelve un vector columna. Bueno, sí y no; vamos a verlo más despacio.
\paragraph{Vectores.}
Cuando introducimos los vectores, distinguimos entre vectores filas y columna, definiéndolos como matrices de una sola fila o una sola columna. Sin embargo, en Numpy, se sigue un criterio distinto que permite generalizar el concepto de matriz asociándolo con el de tensor. Sin entrar en detalles\footnote{Una definición formal del concepto de tensor, queda fuera del alcance de estos apuntes.}, podemos decir que un tensor es un objeto algebráico caracterizado por dos parámetros; el orden y la dimensión. Así un escalar $a \in \mathbb{R}$ es un tensor de orden cero. Un vector $b \in \mathbb{R}^n$ es un tensor de orden 1 y dimesión $n$. Una matriz $A \in \mathbb{R}^{m\times n}$ Es un tensor de orden dos y dimensiones $m,n$. Un tensor de orden 3, $T \in \mathbb{R}^{n\times m \times l}$, etc. Podemos asociar el orden al número mínimo de índices que necesitamos para definir de forma unívoca los elementos de un Tensor: para un escalar, no nos hace faltar ningún indice, solo tenemos un elemento que es el propio escalar, por tanto le asociamos orden cero. Para un vector es suficiente emplear un índice para definir sus elementos, $b=(b_i),\ i=1,\cdots, n$, $b \in \mathbb{R}^n$. Para una matriz necesito dos índices, $A=(a_{ij}),\ i =1, \cdots n, j = 1,\ \cdots, m$, $A \in \mathbb{R}^{n\times m}$. Para un tensor de orden tres necesitaría tres índices, $T=(T_{ijk}),\ i =1,\cdots, n,\ j =1,\cdots m,\ k = 1,\cdots, l$, $T\in \mathbb{R}^{n\times m \times l}$ y así sucesivamente. Numpy permite definir estructuras de cualquier orden y dimensión que queramos. Pero nosotros nos vamos a limitar a vectores (orden 1) y matrices (orden 2). ¿Tiene sentido entonces distiguir entre vectores fila y columna? Solo si consideramos siempre los vectores como matrices (orden 2) y dimesiones $1\times n$ (vector fila) ó $n \times 1$ (vector columna). Para Numpy, sin embargo, vectores y matrices son estructuras de distinto orden. Veamos con algunos ejemplo cómo se diferencian. Para verlo mejor podemos emplear la propiedad \mintinline{python}{shape} de los arrays en numpy, Dicha propiedad nos devuelve una tupla con las dimensiones del array, el número de elementos que contine la tupla nos da el orden,
\switchcolumn
Line [90] extracts a row vector from the first row of matrix \mintinline{python}{D}. Line [91] extracts a $2\times 2$ matrix using the four entries located on the left-up corner of the original, \mintinline{python}{D}, matrix. Line [92] extracts a single matrix entry, but notice that it is a $1\times 1$ matrix. Thus, this result is different than the result achieved when we directly use the indexes of the entry: \mintinline{python}{D[2,1]}. Line [93] returns a row vector with the matrix's last row entries. Lastly, line [95] returns a column vector with the matrix's last column entries.
We have said that line [95] returns a column vector. Well, yes and no; let's examine it in more detail.
\paragraph{Vectors.} When we introduced vectors in the previous section, we distinguished between row and column vectors, defining them as matrices with a single row or column. Nevertheless, Numpy follows another criterion that allows us to generalise the idea of matrix, linking it with the concept of tensor. we do not get into details\footnote{A formal definition of tensors is far beyond the scope of these notes.} and simply say that a tensor is an algebraic object defined by two parámeters, its order, and its dimension. So, a scalar $a \in \mathbb{R}$ is a tensor of order zero. A vector $b \in \mathbb{R}^n$ is a tensor of order one and dimension $n$. A matrix $A\in \mathbb{R}^{m\times n}$ is a tensor of order two and dimensions $m,n$. A third order tensor, $T\in\mathbb{R}^{n\times m\times l}$, etc. We can relate the order with the minimum number of indexes we need to univocally define the tensor entry: for a scalar, we don't need an index at all; we have only a single entry, the scalar itself. For this reason, we associate scalars with a zero-order tensor. For a vector, it is enough to use a single index to define its entries, $b=(b_i), i = 1,\cdots, n,\ b \in \mathbb{R}^n$. For a matrix, we need two indexes, $A = (a_{ij}), i =1,\dots,n,\ j = 1,\dots,m,\ A \in \mathbb{R}^{n\times m}$. For third-order tensors, we need three indexes, $T=(T_{ijk}),\ i =1,\cdots, n,\ j =1,\cdots m,\ k = 1,\cdots, l$, $T\in \mathbb{R}^{n\times m \times l}$ and so on. In Numpy, we can define structures of whatever order and dimensions we want, but we will only use vectors (order 1) and matrices (order 2). Has, then, any sense to distinguish between row and column vector? Only if we always consider vectors as matrices (order 2) and dimensions $1\times n$ (row vector) or $n\times 1$ (column vector). For Numpy, however, vectors an matrices are structures of different order. Let's see some examples of their differences. To appreciate it better, we can use the Numpy arrays attribute \mintinline{python}{shape}, which gives us a tuple containing the dimensions of the array. The number of entries of the tuple tells us the order of the array,
\end{paracol}
\begin{center}
\begin{minipage}{0.3\textwidth}
\begin{minted}{python}
In [23]: D
Out[23]:
array([[ 1., 2., 3.],
[ 4., 5., 6.],
[-2., -3., 0.],
[ 3., 2., 1.]])
In [24]: D.shape
Out[24]: (4, 3)
In [25]: D[1,1]
Out[25]: 5.0
In [26]: D[1,1].shape
Out[26]: ()
In [27]: D[1,1:2]
Out[27]: array([5.])
In [28]: D[1,1:2].shape
Out[28]: (1,)
\end{minted}
\end{minipage}
\end{center}
\begin{center}
\begin{minipage}{0.3\textwidth}
\begin{minted}{python}
In [29]: D[1:2,1:2]
Out[29]: array([[5.]])
In [30]: D[1:2,1:2].shape
Out[30]: (1, 1)
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
Empezamos con la matriz \mintinline{python}{D} de ejemplos anteriores. Para obtener sus dimensiones empleamos \mintinline{python}{D.shape}. El resultado es una tupla compuesta de dos elementos, puesto que es una matriz y, por tanto su orden es dos. El primer elemento no da la dimensión de sus columnas, es decir, el número de filas. El segundo elemento nos da la dimensión de sus filas, es decir el número de columnas.
En la línea [25] extraemos el elemento que ocupa la posición $[1,1]$. En la [26] cuando tratamos de obtener sus dimensiones, nos da una tupla vacía, porque es un escalar y su orden es cero. En la línea [27] le hemos pedido a Numpy que nos de los elementos de la fila $1$ de la matriz \mintinline{python}{D} que ocupan las columnas desde la $1$ hasta la $1$. Es decir, hacemos referencia al mismo elemento de la matriz, sin embargo el resultado no es exáctamente el mismo. Nos ha devuelto un array con el elemento seleccionado. Cuando el la línea [28] pedimos sus dimensiones, obtenemos una tupla con un único elemento \mintinline{python}{(1,)}. Es decir, el orden del array es $1$, se trata de un vector, y tiene de dimensión $1$, el vector solo tiene un elemento.
Por último, en la línea [29] volvemos a pedir a Python que nos de los elementos de la matriz \mintinline{python}{D}, que ocupan las filas desde la $1$ hasta la $1$ y las columnas desde la $1$ hasta la $1$, el resultado es ahora una matriz, podemos ver en la línea \mintinline{python}{out [29]} que el numero $5$ aparece ahora encerrado entre dos pares de corchetes. Cuando en la línea [30], preguntamos por su \mintinline{python}{shape}, nos devuelve una tupla con dos elementos --el orden del array es $2$, puesto que se trata de una matriz-- y sus dimensiones son una fila y una columna, puesto que la matriz solo tiene un elemento.
Vamos a completar nuestro estudio de los arrays en Python, extrayendo ahora partes más grandes de la misma matriz \mintinline{python}{D},
\switchcolumn
We begin with the same matrix \mintinline{python}{D} we use in previous examples. To get its dimensions, we use \mintinline{python}{D.shape}. The result is a tuple of two entries because it is a matrix, and thus, its order is two. The first entry gives us its column dimension, that is, its number of rows. The second entry is its row dimension, that is, its number of columns.
In line [25] we extract the entry located at position $[1,1]$. In line [26] when we try to get its dimension, Numpy returns an empty tuple because it is a scalar and its order is zero. In line [27], we ask Numpy that retrieve the entries of row $1$ of the matrix \mintinline{python}{D} that fill the columns $1$ to $1$. Thus, we are making reference to the same entry of the matrix as in the previous case. However, the result is not exactly the same. Numpy retrieves an array with the selected entry. When we ask for its dimensions in line [28] we get a tuple with a single entry \mintinline{python}{(1,)}. Then, the order of the array is one. It is a vector with a single entry.
Finally, in line [29], we ask Numpy to retrieve the entries of matrix \mintinline{python}{D} with fill the rows from $1$ to $1$ and the columns from $1$ to $1$. Thus, the result is now a matrix, We can see in line \mintinline{python}{out [29]} that the number $5$ is enclosed in two pair of square brackets. When in line [30], we ask for its \mintinline{python}{shape}, we get a tuple with two entries --now the order of the array is two, because it is a matrix-- and their dimension are one row and one column as far as the matrix has a single entry.
We are going to complete our study on Numpy arrays, extracting larger parts of the same matrix,
\end{paracol}
\begin{center}
\begin{minipage}{0.3\textwidth}
\begin{minted}{python}
In [9]: D
Out[9]:
array([[ 1., 2., 3.],
[ 4., 5., 6.],
[-2., -3., 0.],
[ 3., 2., 1.]])
In [10]: D[1,:]
Out[10]: array([4., 5., 6.])
In [11]: D[:,1]
Out[11]: array([ 2., 5., -3., 2.])
In [12]: D[1:2,:]
Out[12]: array([[4., 5., 6.]])
\end{minted}
\end{minipage}
\end{center}
\begin{center}
\begin{minipage}{0.3\textwidth}
\begin{minted}{python}
In [13]: D[:,1:2]
Out[13]:
array([[ 2.],
[ 5.],
[-3.],
[ 2.]])
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
En el primer caso, línea [10], hemos extraido toda la segunda fila de la matriz \mintinline{python}{D}, el resultado es un vector, por tanto tiene orden $1$ y dimensión $3$. En la línea [11] hemos extraido la primera columna y el resultado es de nuevo un vector, por tanto tiene orden $1$ y la dimensión esta vez $4$. En la línea [12] extraemos todas las columnas de las filas que van desde la segunda hasta la segunda. El resultado es una matriz, ya que el orden del array extraído es $2$, y la dimensiones será $1$ para las filas y $3$ para las columna. Es lo más parecido a un vector 'fila' que podemos obtener con Numpy. Por último, en la línea [13], extraemos todas las filas de las columnas que van desde la segunda hasta la segunda. El resultado es de nuevo una matriz, porque el array extraido tiene orden dos, pero las dimensiones son ahora $4$ para las filas y $1$ para las columnas, lo podemos identificar con un vector columna de los descritos antes.
Evidentemente, podemos tambier extraer de una matriz bloque (submatrices), indicando las filas y columnas que queremos extraer de la matriz original. por ejemplo,
\switchcolumn
In the first case, line [10] we get the whole second row of matrix \mintinline{python}{D}. The result is a vector and has order $1$ and dimension $3$. In line [11], we extract the first column of the matrix, and the result is again a vector. This time the order is $1$, and the dimension is $4$. In line [12] we extract all columns belonging to rows second to second. The result is a matrix because the order of the extracted array is two. The dimensions are $1$ for the rows and $3$ for the columns. It is the most similar to a 'row' vector we can get using Numpy. Lastly, in line [13], we extract all the rows belonging to columns second to second. the result is again a matrix because the array obtained has order two, but the dimensions are now $4$ for the rows and $1$ for the columns, we could identify it as a column vector of those described above.
Indeed, we can also extract a block matrix (submatrices), using indexes to define the rows and columns we want to obtain from the original matrix,
\end{paracol}
\begin{center}
\begin{minipage}{0.3\textwidth}
\begin{minted}{python}
In [20]: D
Out[20]:
array([[ 1., 2., 3.],
[ 4., 5., 6.],
[-2., -3., 0.],
[ 3., 2., 1.]])
In [21]: D[1:4,1:3]
Out[21]:
array([[ 5., 6.],
[-3., 0.],
[ 2., 1.]])
In [22]: D[1:3,0:2]
Out[22]:
array([[ 4., 5.],
[-2., -3.]])
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
\section{Operaciones matriciales}\label{opmatr} \index{Matrices! Operaciones Matriciales}
A continuación definiremos las operaciones matemáticas más comunes, definidas sobre matrices. Vamos a empezar por aquellas que se realizan elemento a elemento, entre aquellos elementos que ocupan la misma posición en las matrices que se operan,
\paragraph{Suma.} La suma de dos matrices, se define como la matriz resultante de sumar los elementos que ocupan en ambas la misma posición. Solo está definida para matrices del mismo orden,
\switchcolumn
\section{Matrix Operations}\index[eng]{Matrices! Matrix Operations}
In this section we will define the most common mathematical operation for matrices. We are going to beging for those operation that are carried out, entry by entry, between those entries which occupy the same place in the operating matrices.
\paragraph{Addition.} Addition of two matrix, the result is a new matrix obtained adding the entries which ocuppy the same position in both matrices. It is denied only for matrix of the same dimensions,
\end{paracol}
\begin{gather*}
C=A+B\\
c_{ij}=a_{ij}+b_{ij}\\
\\
\begin{pmatrix}
1& 2& 3\\
4& 5& 6\\
7& 8& 9\\
\end{pmatrix} =
\begin{pmatrix}
1& 3& 5\\
3& 5& 7\\
5& 7& 9\\
\end{pmatrix} +
\begin{pmatrix}
0& -1& -2\\
1& 0& -1\\
2& 1& 0\\
\end{pmatrix}
\end{gather*}
\begin{paracol}{2}
La suma de matrices cumple las siguientes propiedades,
\begin{enumerate}
\item Asociativa: $(A+B)+C=A+(B+C)$
\item Conmutativa: $A+B=B+A$
\item Elemento neutro: $O_{n\times m}+A_{n\times m}=A_{m\times m}$ El elemento neutro $O_{n\times m}$ de la suma de matrices de orden $n\times m$ es la matriz nula de dicho orden, ---compuesta exclusivamente por ceros--- .
\item Elemento opuesto: La opuesta a una matriz se obtiene cambiando de signo todos sus elementos, $A_{op}=-A$
\end{enumerate}
En numpy el signo $+$ se también utiliza para representar la suma de matrices, por lo que la suma de dos matrices puede obtenerse directamente como,
\switchcolumn
Matrix addition fulfil the following properties,
\begin{enumerate}
\item Asociative: $(A+B)+C=A+(B+C)$
\item Conmutative: $A+B=B+A$
\item Identity element: $O_{n\times m}+A_{n\times m}=A_{m\times m}$ The identity element $O_{n\times m}$ of the addition of $n\times m$ matrices is the null matriz of this dimensions, ---an only zeros matrix--- .
\item Inverse: we get the addition inverse of a matrix changing the sings of all its entries $A_{inv}=-A$
\end{enumerate}
In numpy, the symbol $+$ also represents the matrix addition. Thus, you can use it to add two matrices in the same way you use it to add two numbers,
\end{paracol}
\begin{center}
\begin{minipage}{.5\textwidth}
\begin{minted}{python}
In [0]: import numpy as np
In [1]: A = np.array([[1,3,5],[2,4,6]])
In [2]: A
Out[2]:
array([[1, 3, 5],
[2, 4, 6]])
In [3]: B = np.array([[3,-2,0],[1,-4,3]])
In [4]: A+B
Out[4]:
array([[4, 1, 5],
[3, 0, 9]])
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
En numpy, podemos crear una matriz de cualquier orden, compuesta exclusivamente por ceros mediante el comando\\ \mintinline{python}{numpy.zeros((m,n))}, donde $m$ es el número de filas y $n$ el de columnas de la matriz de ceros resultante. Si damos un único valor, \mintinline{python}{numpy.zeros(n)}, obtenedremos un vector formado por $n$ ceros.
\switchcolumn
We can use the Numpy command\\ \mintinline{python}{numpy.zeros((m,n))} to create a matrix, of whatever dimension, with all ist entries equal to zero. $m$ stands for the number of rows and $n$ for the number of columns of the zero matrix we want to create. If we use the command \mintinline{python}{numpy.zeros(n)} with a single value instead a tuple, then we will obtain a vector built up of $n$ zeros..
\end{paracol}
\begin{center}
\begin{minipage}{.3\textwidth}
\begin{minted}{python}
In [375]: np.zeros(3)
Out[376]: array([0., 0., 0.])
In [377]: np.zeros((3,1))
Out[378]:
array([[0.],
[0.],
[0.]])
In [379]: np.zeros((1,3))
Out[380]: array([[0., 0., 0.]])
In [381]: np.zeros((3,3))
Out[382]:
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
In [383]: Z = np.zeros((2,3))
In [384]: A+Z
Out[385]:
array([[1., 3., 5.],
[2., 4., 6.]])
\end{minted}
\end{minipage}
\end{center}
\begin{center}
\begin{minipage}{.3\textwidth}
\begin{minted}{python}
In [386]: Aop = -A
In [387]: A+Aop
Out[388]:
array([[0, 0, 0],
[0, 0, 0]])
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
\paragraph{Multiplicación elemento a elemento.} No es propiamente una operación matricial. Dadas dos matrices $A$ y $B$ de las mismas dimensiones, si las multiplicamos elemento a elemento, obtendremos una nueva matriz $C$ tal que, $c_{i,j} = a_{i,j}b_{i,j}$. Al igual que la suma, el producto elemento a elemento es asociativo y conmutativo.
En Numpy el simbolo para la multiplicación elemento a elemento es el asterisco *,
\switchcolumn
\paragraph{Entry-wise multiplication} This is not a proper matrix (algebraic) operation. You can get the entry-wise product of two matrices, $A$ and $B$, with the same dimensions to obtain a new matrix $C$ which entries are $c_{i,j} = a_{i,j}b_{i,j}$. This product, like the matrix addition, is conmutative and asociative. In numpy the entry-wise multiplication symbol is the asterisk *,
\end{paracol}
\begin{center}
\begin{minipage}{.5\textwidth}
\begin{minted}{python}
In [49]: A
Out[49]:
array([[1, 2],
[2, 0],
[3, 5]])
In [50]: B
Out[50]:
array([[-3, 1],
[ 0, 2],
[ 1, -4]])
In [51]: A*B
Out[51]:
array([[ -3, 2],
[ 0, 0],
[ 3, -20]])
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
\paragraph{División elemento a elemento.} Es análoga a la multiplicación que acabamos de ver. Si dividimos elemento a elemento una matrix $A$ entre otra matriz $B$, ambas de las mismas dimensiones, obtenemos una matriz $C$ cuyos elementos cumplen $c_{ij} = a_{ij}/b_{ij}$. El símbolo que se emplea es el mismo de la división ordinaria entre números.
En el ejemplo siguiente, dividimos entre sí las dos matrices del ejemplo anterior, es interesante observar como Python nos advierte de la división entre cero, y asigna al elemento en que se produce el valor \mintinline{python}{inf}.
\switchcolumn
\paragraph{Entry-wise division.} It is very much alike the element-wise product. If we divide entry-wise a matrix $A$ by another matrix $B$, both of the same dimensions, we get a new matrix $C$ which entries are $c_{ij} = a_{ij}/b_{ij}$. For matrix entry-wise division, we use the same symbol as in the ordinary number division.
In the following example, we divide the two matrix of the previous example, it is interesting to see how Python warnings us of a division by zero, and assigns to the resulting entry the value \mintinline{python}{inf}.
\end{paracol}
\begin{center}
\begin{minipage}{\textwidth}
\begin{minted}{python}
In [52]: A/B
/tmp/ipykernel_10098/713994841.py:1: RuntimeWarning: divide by zero encountered
in divide A/B
Out[52]:
array([[-0.33333333, 2. ],
[ inf, 0. ],
[ 3. , -1.25 ]])
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
\paragraph{Transposición.} Dada una matriz $A$, su transpuesta $A^T$ se define como la matriz que se obtiene intercambiando sus filas con sus columnas.
\switchcolumn
\paragraph{Transposition.} The transpose matrix $A^T$ of a matrix $A$ is the matrix we obtain intechanging its rows and columns.
\end{paracol}
\begin{gather*}
A \rightarrow A^T\\
a_{ij} \rightarrow a_{ji}\\
A=
\begin{pmatrix}
1& -3& 2 \\
2& 7& -1
\end{pmatrix} \rightarrow
A^T=
\begin{pmatrix}
1& 2 \\
-3& 7\\
2 & -1
\end{pmatrix}
\end{gather*}
\begin{paracol}{2}
En numpy, la operación de transposición se indica mediante un punto y la letra T, \mintinline{python}{A.T}. Solo tiene sentido aplicarla para matrices; si transponemos un vector volvemos a obtener el mismo vector.
\switchcolumn
In Numpy the traspose matrix is obtained adding a point an the letter T to the matrix we wish to transpose, \mintinline{python}{A.T}. It only has sense for matrices. If we try to transpose a vector wi will optain the same vector again.
\end{paracol}
\begin{center}
\begin{minipage}{0.5\textwidth}
\begin{minted}{python}
In [375]: A
Out[375]:
array([[1, 3, 5],
[2, 4, 6]])
In [376]: A.T
Out[376]:
array([[1, 2],
[3, 4],
[5, 6]])
In [377]: B = np.array([1,2,3])
In [378]: B.T
Out[378]: array([1, 2, 3])
In [379]: C = np.array([[1,2,3]])
In [380]: C
Out[380]: array([[1, 2, 3]])
\end{minted}
\end{minipage}
\end{center}
\begin{center}
\begin{minipage}{0.5\textwidth}
\begin{minted}{python}
In [381]: C.T
Out[381]:
array([[1],
[2],
[3]])
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
Una matriz cuadrada se dice que es simétrica si coincide con su transpuesta,
\switchcolumn
A square matrix is antisimetric if it is equal to its traspose matrix,
\end{paracol}
\begin{gather*}
A=A^T\\
a_{ij}=a{ji}\\
A=A^T=
\begin{pmatrix}
\ 1&\ 3&-3\\
\ 3&\ 0&-2\\
-3&-2&\ 4
\end{pmatrix}
\end{gather*}
\begin{paracol}{2}
Una matriz cuadrada es antisimétrica cuando cumple que $A=-A^T$. Cualquier matriz cuadrada se puede descomponer en la suma de una matriz simétrica más otra antisimétrica.
La parte simétrica puede definirse como,
\switchcolumn
A square matrix is antisymmetric when it meets that $A=A^T$. Any square matrix can be split in the sum of two matrix, one symmetric and another antisymmetric
The symmetric part can be defined as,
\end{paracol}
\begin{equation*}
A_S=\frac{1}{2} \left( A+A^T \right)
\end{equation*}
\begin{paracol}{2}
y la parte antisimétrica como,
\switchcolumn
An the antisimetric part as,
\end{paracol}
\begin{equation*}
A_A=\frac{1}{2}\left( A-A^T \right)
\end{equation*}
\begin{paracol}{2}
Así, por ejemplo,
\switchcolumn
For instance,
\end{paracol}
\begin{equation*}
A=A_S+A_A \rightarrow
\begin{pmatrix}
1& 2& 3\\
4& 5& 6\\
7& 8& 9\\
\end{pmatrix} =
\begin{pmatrix}
1& 3& 5\\
3& 5& 7\\
5& 7& 9\\
\end{pmatrix} +
\begin{pmatrix}
0& -1& -2\\
1& 0& -1\\
2& 1& 0\\
\end{pmatrix}
\end{equation*}
\begin{paracol}{2}
Por último, la transpuesta de la suma de matrices cumple,
\switchcolumn
The transpose of the addition of matrix meets,
\end{paracol}
\begin{equation*}
(A+B)^T=A^T+B^T
\end{equation*}
\begin{paracol}{2}
\paragraph{Producto de una matriz por un escalar.} El producto de una matriz $A$ por un número $b$ es una matriz del mismo orden que $A$, cuyos elementos se obtienen multiplicando los elementos de $A$ por el número $b$,
\switchcolumn
\paragraph{Product of a matrix and a scalar.} The product of a matrix $A$ for a number $b$ is a matrix with the same dimensions as $A$. We obtain the entry of this product multiplying the elemetns of $A$ by the number $b$,
\end{paracol}
\begin{gather*}
C=b\cdot A \rightarrow c_{ij}=b\cdot a_{ij}\\
3\cdot
\begin{pmatrix}
1& -2& 0\\
2& 3& -1&
\end{pmatrix}=
\begin{pmatrix}
3& -6& 0\\
6& 9& -3&
\end{pmatrix}
\end{gather*}
\begin{paracol}{2}
En Python, el símbolo \mintinline{python}{*} se emplea también para representar el producto de una matriz por un número
\switchcolumn
In Python we also use the symbol \mintinline{python}{*} to represent the product of a matrix by a number.
\end{paracol}
\begin{center}
\begin{minipage}{0.5\textwidth}
\begin{minted}{python}
In [391]: A
Out[391]:
array([[ 3, -5, -2, 1],
[ 2, 3, 4, 5]])
In [394]: A*5
Out[394]:
array([[ 15, -25, -10, 5],
[ 10, 15, 20, 25]])
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
\paragraph{Producto escalar de dos vectores.} Dados vectores de la misma dimensión $m$ se define su producto escalar como,
\switchcolumn
\paragraph{Dot product of two vectors}
For two vectors of the same dimension, we define the the dot product as,
\end{paracol}
\begin{gather*}
a\cdot b=\sum_{i=1}^na_ib_i\\
\begin{pmatrix}
1\\
3\\
4
\end{pmatrix}\cdot
\begin{pmatrix}
1\\
-2\\
0
\end{pmatrix}
=1\cdot 1+3 \cdot (-2)+ 4 \cdot 0= -5
\end{gather*}
\begin{paracol}{2}
El resultado de producto escalar de dos vectores, es siempre un número; se multiplican los entre sí los elementos de los vectores que ocupan idénticas posiciones y se suman los productos resultantes.
\paragraph{Producto matricial}
El producto de una matriz de orden $n\times m$ por una matriz $m\times l$, es una nueva matriz de orden $n\times l$, cuyos elementos se obtiene de acuerdo con la siguiente expresión,
\switchcolumn
The dot product result is always a number; we multiply the entry which take the same place in both vectors and then, we sum the resulting products.
\paragraph{Matrix product} The matrix product of a $n \times m$ matrix by a $mtimes l$ matrix is a new matrix which dimensions are $n\times l$, We obtain the entries of the resulting matrix according with the following expression,
\end{paracol}
\begin{equation*}
P=A\cdot B \rightarrow a_{ij}=\sum_{t=1}^m a_{it}b_{tj}
\end{equation*}
\begin{paracol}{2}
Por tanto, el elemento de la matriz producto que ocupa la fila $i$ y la columna $j$, se obtiene multiplicando por orden los elementos de la fila $i$ de la matriz $A$ con los elementos correspondientes de la columna $j$ de la matriz $B$, y sumando los productos resultantes
Para que dos matrices puedan multiplicarse es imprescindible que el número de columnas de la primera matriz coincida con el número de filas de la segunda.
Podemos entender la mecánica del producto de matrices de una manera más fácil si consideramos la primera matriz como un grupo de vectores fila,
\switchcolumn
So, we get the entry of the product matrix, which occupies the row $i$ and the column $j$, by multiplying in turn the entries of the row $i$ of matrix $A$ with the entries of the column $j$ of matrix $B$ and adding up the resulting products.
Two matrix can be multiplied only if the number of columns in the first matrix dimension is equal to the second matrix row dimension.
We may understand better the matrix product mechanism if we consider the first matrix as a group of row vectors,
\end{paracol}
\begin{equation*}
\begin{aligned}
A_1=\begin{pmatrix}
a_{11}& a_{12}& \cdots a_{1n}
\end{pmatrix}\\
A_2=\begin{pmatrix}
a_{21}& a_{22}& \cdots a_{2n}
\end{pmatrix}\\
\vdots \ \ \ \ \ \ \ \ \ \ \\
A_m=\begin{pmatrix}
a_{m1}& a_{m2}& \cdots a_{mn}
\end{pmatrix}
\end{aligned} \ \rightarrow \
A=\begin{pmatrix}
a_{11}& a_{12}& \cdots a_{1n}\\
a_{21}& a_{22}& \cdots a_{2n}\\
\vdots& \vdots& \cdots& \vdots \\
a_{m1}& a_{m2}& \cdots a_{mn}
\end{pmatrix}
\end{equation*}
\begin{paracol}{2}
y la segunda matriz como un grupo de vectores columna,
\switchcolumn
An the second matrix as a group of column vectors.
\end{paracol}
\begin{equation*}
\begin{aligned}
B_1=\begin{pmatrix}
b_{11}\\ b_{21}\\ \vdots \\ b_{n1}
\end{pmatrix}&
B_2=\begin{pmatrix}
b_{12}\\ b_{22}\\ \vdots\\ b_{n2}
\end{pmatrix} &
\cdots \ \ &
B_3=\begin{pmatrix}
b_{1m}\\ b_{2m}\\ \vdots b_{nm}
\end{pmatrix}
\end{aligned} \ \rightarrow \
B=\begin{pmatrix}
b_{11}& b_{12}& \cdots b_{1n}\\
b_{21}& b_{22}& \cdots b_{2n}\\
\vdots& \vdots& \cdots& \vdots \\
b_{m1}& b_{m2}& \cdots b_{mn}
\end{pmatrix}
\end{equation*}
\begin{paracol}{2}
Podemos ahora considerar cada elemento $p_{ij}$ de la matriz producto $P=A\cdot B$ como el producto escalar del vector fila $A_i$ for el vector columna $B_j$, $p_{ij}=A_i\cdot B_j$.
Es ahora relativamente fácil, deducir algunas de las propiedad del producto matricial,
\begin{enumerate}
\item Para que dos matrices puedan multiplicarse, es preciso que el número de columnas de la primera coincida con el numero de filas de la segunda. Además la matriz producto tiene tantas filas como la primera matriz y tantas columnas como la segunda.
\item El producto matricial no es conmutativo. En general $A\cdot B \neq B \cdot A$
\item $(A\cdot B)^T=B^T\cdot A^T$
\end{enumerate}
\switchcolumn
we may consider the consider each entry $p_{ij}$ of the product matrix $P=A\cdot B$ as a escalar product of the row vector $A_i$ and the column vector $B_j$, $p_{ij} = A_i\cdot B_j$. Now we can easily find out some interesting properties of the matrix product.
\begin{enumerate}
\item Two matrices can be multiplyed only if the number of columns of the first matrix meet the number of columns of the second one. Besides, the product matrix has so meny row as the first matrix and so many columns as the second one.
\item Matrix produc it is not conmutative. In general, $A\cdot B \neq B \cdot A$
\item $(A\cdot B)^T=B^T\cdot A^T$
\end{enumerate}
\end{paracol}
\begin{paracol}{2}
En Numpy se emplea el símbolo \mintinline{python}{@} para representar el producto escalar, el producto de un vector por una matriz y el producto matricial. En todos los casos, es preciso que las dimensiones internas de los objetos que se multiplican coincidan. A continuación se muestran algunos ejemplos,
\switchcolumn
Numpy uses the symbol \mintinline{python}{@} to represent the scalar product, the product of a matrix and a vector and the matrix product. In any case, it is necessary that the inner dimensions of factor objects meet. Next we show some matrix multiplication examples,
\end{paracol}
\begin{center}
\begin{minipage}{0.7\textwidth}
\begin{minted}{python}
In [382]: a = np.array([1,2,3,4])
In [383]: b = np.array([-1,2,0,-3])
In [384]: a@b
Out[384]: -9
In [386]: A = np.array([[3,-5,-2,1],[2,3,4,5]])
In [387]: A
Out[387]:
array([[ 3, -5, -2, 1],
[ 2, 3, 4, 5]])
In [388]: A@b
Out[388]: array([-16, -11])
In [389]: b@A.T
Out[389]: array([-16, -11])
\end{minted}
\end{minipage}
\end{center}
\begin{center}
\begin{minipage}{0.7\textwidth}
\begin{minted}{python}
In [390]: b@A
Traceback (most recent call last):
Cell In[390], line 1
b@A
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0,
with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 4)
In [398]: B
Out[398]:
array([[ 0, -1],
[-1, 0],
[ 2, 3],
[ 3, 4]])
In [399]: A@B
Out[399]:
array([[ 4, -5],
[20, 30]])
In [400]: B@A
Out[400]:
array([[-2, -3, -4, -5],
[-3, 5, 2, -1],
[12, -1, 8, 17],
[17, -3, 10, 23]])
\end{minted}
\end{minipage}
\end{center}
\begin{paracol}{2}
En la Línea In [384] se ha calculado el producto escalar de los vectores \mintinline{python}{a} y \mintinline{python}{b}. En este caso, la única condición requerida es que tengan la misma dimensión. En la línea In [388] se calcula el producto de la matriz \mintinline{python}{A} por el vector \mintinline{python}{b}. El requisito ahora es que la dimensión de la matriz ($2\times 4$), que corresponde al número de columnas, coincida con la única dimensión del vector ($4$). En la línea In [389] calculamos el producto del vector \mintinline{python}{b} por la transpuesta de la matriz \mintinline{python}{A}. La operación es posible porque la única dimensión del vector y coincide con la dimensión de la matriz transpuesta $(4\time2)$, que corresponde con a número de filas. Sin embargo, no es posible calcular el producto del vector \mintinline{python}{b} por la matriz \mintinline{python}{A}, ya que la dimensión del vector no coincide con la primera dimensión de la matriz $(2\times4)$. En la línea In [399] hemos multiplicado las matrices \mintinline{python}{A} $(2\times 4$) por la matriz \mintinline{python}{B} $(4\times 2)$. Como coinciden las dimensiones ``internas'', --numero de columnas de la primera matriz con número de filas de la segunda-- La operación puede llevarse a cabo. Si invertimos el orden de las matrices, (línea In [400]) el producto también es posible, ya que en también coincidirían las dimensiones ``internas''. Sin embargo, es fácil ver que los resultados son complementamente distintos.
\switchcolumn
In line In[384] we calcuted the scalar product of vectors \mintinline{python}{a} and \mintinline{python}{b}. In this case, the only requirement is that both vectors have the same dimension. In line In [388] we calculated the product of matrix \mintinline{python}{A} and the vector \mintinline{python}{b}. Now the requirement is the dimension of the matrix ($2\times 4$), corresponding to the number of columns, meets the the single dimension of the vector ($4$). In line [389], we multiplied vector \mintinline{python}{b} with the transpose of matrix \mintinline{python}{A}. This operation can be carried out because the single dimension of vector \mintinline{python}{b} is the same as the dimension of the transpose of the matrix $(4\times 2)$, which corresponds with the number of rows of the matrix. However, we cannot multiply vector \mintinline{python}{b} by matrix \mintinline{python}{A} because the dimension of the vector does not meet the first dimension of the matrix $(2\times 4)$. In line In [399] we multiplied matrix \mintinline{python}{A} $(2\times 4)$ by matix \mintinline{python}{B} $(4\times 2)$. We can carry out the operation because the ``inner'' dimensions of the matrices --number of columns of the first matrix and number of rows of the second one--, meet. If we invert the order of the matrices (line In [400]), we can still multiply the matrix because, in this particular case, the new ``inner'' dimensions also meet. However, the result is entirely different
\end{paracol}
\begin{paracol}{2}
\paragraph{Matriz identidad} La matriz identidad de orden $n\times n$ se
define como:
\switchcolumn
\paragraph{The identity matrix } The identity matrix of dimension $n\times n$ is defined as:
\end{paracol}
\begin{equation*}
I_n= \left\{
\begin{aligned}
i_{ll}&=1\\
i_{kj}&=0, \ k\neq j
\end{aligned}