CasADi: explicación detallada de los tipos de datos e introducción a las operaciones básicas


1. Símbolos de uso común

1.1 símbolo SX

  El tipo de datos SX se utiliza para representar matrices cuyos elementos constan de expresiones simbólicas que constan de una secuencia de operaciones unarias y binarias. Para ver cómo funciona esto en la práctica, inicie un shell Python interactivo (por ejemplo, escribiendo ipython desde una terminal Linux o en un entorno de desarrollo integrado como Spyder) o inicie MATLAB o la interfaz gráfica de usuario de Octave. Suponiendo que CasADi esté instalado correctamente, puede importar la biblioteca a su espacio de trabajo de la siguiente manera:

from casadi import *

Cree una variable x usando la siguiente sintaxis:

x = MX.sym("x")
print(x)

El resultado después de ejecutar es:

X

El código anterior crea una matriz de 1 × 1, que es una primitiva simbólica llamada x (que es un escalar). Esto es solo un nombre para mostrar, no un identificador. Varias variables pueden tener el mismo nombre y seguir siendo diferentes. El identificador es el valor de retorno. Además, se puede llamar a la función SX.sym (con parámetros) para crear variables simbólicas con valores vectoriales o matriciales:

y = SX.sym('y',5)
Z = SX.sym('Z',4,2)
print(y)
print(z)

El resultado después de ejecutar es:

[y_0, y_1, y_2, y_3, y_4]
[[Z_0, Z_4],
 [Z_1, Z_5],
 [Z_2, Z_6],
 [Z_3, Z_7]]

El código anterior crea una matriz de 5×1 (es decir, un vector) y una matriz de 4×2 con primitivas simbólicas respectivamente. SX.sym es una función (estática) que devuelve una instancia de SX. Después de declarar una variable, ahora se pueden formar expresiones de forma intuitiva:

f = x**2 + 10
f = sqrt(f)
print(f)

El resultado después de ejecutar es:

raíz cuadrada((10+cuadrada(x)))

Además de esto, es posible crear instancias SX sin constantes:

B1 = SX.zeros(4,5): # 一个全零的密集 4×5 空矩阵 
B2 = SX(4,5): # 全零的稀疏 4×5 空矩阵 
B4 = SX.eye(4): # 稀疏的4×4矩阵,对角线为1 
print(B1)
print(B2)
print(B4)

El resultado después de ejecutar es:

B1: @1=0,
[[@1, @1, @1, @1, @1],
 [@1, @1, @1, @1, @1],
 [@1, @1, @ 1, @1, @1],
 [@1, @1, @1, @1, @1]]
B2:
[[00, 00, 00, 00, 00],
 [00, 00, 00, 00, 00],
 [00, 00, 00, 00, 00],
 [00, 00, 00, 00, 00]]
B4: @1=1,
[[@1, 00, 00, 00],
 [00, @ 1, 00, 00],
 [00, 00, @1, 00],
 [00, 00, 00, @1]]

  Nota : Tenga en cuenta la diferencia entre las expresiones anteriores: al imprimir una expresión con ceros estructurales (elementos en una matriz dispersa que no están asignados explícitamente), estos ceros se representarán como 00 para compararlos con los ceros reales @1 (elementos explícitos reales para asignado por fórmula, use @1 para representar 0 después de imprimir para distinguir la diferencia entre el cero estructural y el cero real).

Además de los métodos de uso anteriores, la siguiente tabla enumera las expresiones SX de uso común:

expresión de función usar
SX.sym(nombre,n,m) Crear una primitiva simbólica de n×m
SX.ceros(n,m) Cree una matriz densa de n por m con todos los elementos cero
SX(n,m) Cree una matriz dispersa de n × m con todos los elementos cero
SX.ones(n,m) Cree una matriz densa de n por m que contenga todos los unos
SX.ojo(n) Cree una matriz diagonal n × n con 1 elementos en la diagonal y ceros estructurales en otros lugares.
SX(tipo_escalar) Crea un escalar (matriz 1×1) usando los valores dados por los argumentos. Este método se puede usar explícitamente, como SX(9), o implícitamente, como 9 * SX.ones(2,2)
SX(tipo_matriz) Crea una matriz de la matriz numérica dada, ya sea como una matriz NumPy o SciPy (en Python) o como una matriz densa o dispersa (en MATLAB/Octave). En MATLAB/Octave, por ejemplo, SX([1,2,3,4]) representa un vector de fila, SX([1;2;3;4]) representa un vector de columna, SX([1,2;3 ,4] ) representa una matriz de 2 × 2 y este método se puede utilizar explícita o implícitamente.
repmat(v,n,m) Repita la expresión v n veces en dirección vertical y m veces en dirección horizontal. Por ejemplo: repmat(SX(3),2,1) crea una matriz de 2×1 con todos los elementos 3.
SX (lista) (solo Python) Cree un vector de columna (matriz n por 1) utilizando los elementos de la lista, como SX([1,2,3,4]). (Tenga en cuenta la diferencia entre las listas de Python y la concatenación horizontal de MATLAB/Octave, ambas usan sintaxis de corchetes)
SX (lista de listas) (solo Python) Cree una matriz densa usando los elementos de la lista, por ejemplo SX([[1,2],[3,4]]) o cree una matriz (1×n usando SX([[1,2,3,4] ]) ) vector de fila.

1.2 símbolos DM

  DM es muy similar a SX, excepto que los elementos distintos de cero son valores numéricos en lugar de expresiones simbólicas. La sintaxis de DM también es la misma que la de SX, excepto por algunas funciones como SX.sym.

  DM se utiliza principalmente para almacenar matrices en CasADi y como entrada y salida de funciones. No está diseñado para su uso en cálculos computacionales intensivos. Para hacer esto, use los tipos de datos densos o dispersos integrados en las matrices MATLAB, NumPy o SciPy en Python, o una biblioteca basada en plantillas de expresión como eigen, ublas o MTL en C++. La conversión entre tipos suele ser sencilla:

C = DM(2,3)

C_dense = C.full()
from numpy import array
C_dense = array(C) # equivalent

C_sparse = C.sparse()
from scipy.sparse import csc_matrix
C_sparse = csc_matrix(C) # equivalent

  Se pueden encontrar más ejemplos del uso de SX en el paquete de ejemplos en http://install.casadi.org/. La documentación sobre características específicas de esta clase (y otras clases), como la API de C++, se puede encontrar en http://docs.casadi.org/.


1.3 notación MX

  La salida del siguiente código es una matriz de 2 × 2. Preste atención a la primera oración aquí @1=3, lo que significa que @1 representa 3 en la salida de la segunda línea . El resultado de salida significa que CasADi es cada uno de los matriz f La entrada crea una nueva expresión (tipo SX).

x = SX.sym('x',2,2)
y = SX.sym('y')
f = 3*x + y
print(f)
print(f.shape)

El resultado después de ejecutar es:

@1=3,
[[(@1 x_0)+y), ((@1 x_2)+y)],
 [((@1 x_1)+y), ((@1 x_3)+y)]]
(2, 2)

  Además del método anterior, también podemos utilizar el segundo tipo de expresión matricial MX, más general. El tipo MX permite la construcción de expresiones que constan de una serie de operaciones básicas al igual que SX. Pero a diferencia de SX, estas operaciones básicas no se limitan a operaciones escalares unarias o binarias ( R → R \mathbb{R}→\mathbb{R}RRR × R → R \mathbb{R}×\mathbb{R}→\mathbb{R}R×RR ). En cambio, las operaciones básicas utilizadas para formar expresiones MX pueden ser la entrada general de valores de matriz dispersa múltiples y la función de salida de valores de matriz dispersa múltiples:R n 1 × m 1 × … × R n N × m N → R p 1 × q 1 × … × R p M × q M \mathbb{R}^{ { n_1}×{m_1}}×…×\mathbb{R}^{ { n_N}×{m_N}}→\mathbb{ R}^{ {p_1 }×{q_1}}×…×\mathbb{R}^{ {p_M}×{q_M}}Rnorte1× metro1××Rnortenorte× metronorteRpag1× q1××Rpagm× qm,Por ejemplo:

x = MX.sym('x',2,2)
y = MX.sym('y')
f = 3*x + y
print(f)
print(f.shape)

El resultado después de ejecutar es:

((3*x)+y)
(2, 2)

  Los dos fragmentos de código anteriores tienen el mismo resultado, la notación MX consta de solo dos operaciones (una multiplicación y una suma), mientras que el equivalente SX tiene ocho (cada elemento consta de dos, f(1,1) consta de (@ 1x_0) y composición y). Por tanto, MX puede resultar más económico cuando se utilizan operaciones con valores vectoriales naturales o matriciales con muchos elementos.

  MX admite la obtención y configuración de elementos utilizando la misma sintaxis que SX, pero la implementación es muy diferente. Por ejemplo, pruebe a imprimir el elemento superior izquierdo de una variable simbólica de 2×2:

x = MX.sym('x',2,2)
print(x[0,0])

La salida debe entenderse como una expresión igual al primer elemento estructuralmente distinto de cero (es decir, índice 0 en C++) de x, que es la primera posición (índice 0) de la matriz, a diferencia de x_0 en el caso SX anterior.

  El uso es similar al configurar elementos:

x = MX.sym('x',2)
A = MX(2,2)
A[0,0] = x[0]
A[1,1] = x[0]+x[1]
print('A:', A)

El resultado después de ejecutar es:

A: (proyecto((ceros(2x2,1nz)[0] = x[0]))[1] = (x[0]+x[1]))

Esta salida puede entenderse como: a partir de una matriz dispersa todo cero, se asigna un elemento a x_0. Luego proyéctelo a una matriz de diferente dispersión y asigne otro elemento a x_0+x_1.


1.4 Mezcla de SX y MX

  No puede multiplicar objetos SX con objetos MX ni realizar ninguna otra operación para mezclar los dos en el mismo gráfico de expresión. Sin embargo, es posible incluir llamadas a funciones definidas por expresiones SX en el gráfico MX. Si necesita mejorar la eficiencia de su programa, puede combinar SX y MX porque la sobrecarga de cada operación de funciones definidas por expresiones SX es mucho menor, lo que permite que el sistema complete una serie de operaciones escalares más rápido. Por lo tanto, las expresiones SX están destinadas a operaciones de bajo nivel, mientras que las expresiones MX se utilizan para implementar operaciones responsables, como la implementación de funciones de restricción para PNL.


1.5 clase dispersa

  Las matrices en CasADi se almacenan utilizando el formato de almacenamiento en columnas comprimidas (CCS). Este es un formato estándar para matrices dispersas que permite el desempeño eficiente de operaciones de álgebra lineal, como operaciones de elementos, multiplicaciones de matrices y transposiciones. En formato CCS, el modo disperso utiliza dimensiones (número de filas y columnas) y dos vectores para decodificar. El primer vector contiene el índice del primer elemento estructuralmente distinto de cero de cada columna, y el segundo vector contiene el índice de fila de cada elemento distinto de cero. Para obtener más detalles sobre el formato CCS, consulte, por ejemplo, la plantilla para soluciones de sistemas lineales en Netlib. Tenga en cuenta que CasADi utiliza el formato CCS para matrices densas y dispersas.

  Los patrones de dispersión en CasADi se almacenan como instancias de la clase Sparsity, que se cuenta por referencia, lo que significa que varias matrices pueden compartir el mismo patrón de dispersión, incluidos gráficos de expresión MX e instancias de SX y DM. Las clases dispersas también se almacenan en caché, lo que significa que siempre se evita la creación de múltiples instancias del mismo patrón disperso.

  La siguiente lista resume las formas más comunes de crear nuevos patrones dispersos:

Nombre de la función Función
Dispersión.densa(n,m) Crea un patrón disperso denso de n×m
Escasez (n, m) Crea un patrón disperso de n×m
Disparidad.diag(n) Crear un patrón disperso diagonal n×n
Escasez.superior(n) Crea un patrón disperso triangular superior n×n
Disparidad.inferior(n) Crea un patrón disperso triangular inferior n×n

  Se pueden utilizar clases dispersas para crear matrices no estándar, por ejemplo:

print(SX.sym('x',Sparsity.lower(3)))

El resultado después de ejecutar es:

[[x_0, 00, 00],
 [x_1, x_3, 00],
 [x_2, x_4, x_5]]

1.5.1 Obtener y establecer elementos en una matriz

  Para obtener o establecer un elemento o un conjunto de elementos en tipos de matrices CasADi (SX, MX y DM), utilizamos corchetes en Python y corchetes en C++ y MATLAB. Siguiendo la convención de estos lenguajes, la indexación comienza en 0 en C++ y Python y en 1 en MATLAB. En Python y C++, permitimos que los índices negativos especifiquen índices que cuentan desde el final. En MATLAB, utilice la palabra clave end para comenzar a indexar desde el final.

  La indexación se puede realizar con uno o dos índices. Usando dos índices, puede acceder a una fila específica (o un grupo o grupos de filas) y una columna específica (o un grupo de columnas). Usando un índice, puede acceder a un elemento (o un grupo de elementos) comenzando desde la esquina superior izquierda y yendo en columnas hasta la esquina inferior derecha. Todos los elementos se cuentan independientemente de si son estructuralmente cero. Por ejemplo:

M = SX([[3,7],[4,5]])
print(M[0,:])
M[0,:] = 1
print(M)

El resultado después de ejecutar es:

[[3, 7]]
@1=1,
[[@1, @1],
 [4, 5]]

  A diferencia de NumPy de Python, los sectores CasADi no son vistas de los datos de la izquierda; en cambio, el acceso al sector copia los datos. Por tanto, en el siguiente ejemplo, la matriz m no ha cambiado en absoluto:

M = SX([[3,7],[4,5]])
M[0,:][0,0] = 1
print(M)

El resultado después de ejecutar es:

[[3, 7],
 [4, 5]]

  A continuación se detalla la obtención y configuración de los elementos de la matriz. Esta discusión se aplica a todos los tipos de matrices de CasADi.

  Obtenga o establezca el acceso a un solo elemento proporcionando un par fila-columna o su índice aplanado (por columnas comenzando desde la esquina superior izquierda de la matriz):

M = diag(SX([3,4,5,6]))
print(M)

El resultado después de ejecutar es:

[[3, 00, 00, 00],
 [00, 4, 00, 00],
 [00, 00, 5, 00],

 [00, 00, 00, 6]]

print(M[0,0])
print(M[1,0])
print(M[-1,-1])

El resultado después de ejecutar es:

3
00
6

  El acceso por sectores significa configurar varios elementos a la vez. Esto es mucho más eficiente que configurar un elemento a la vez. Se puede obtener o configurar un fragmento proporcionando una tupla (inicio, parada, paso). En Python y MATLAB, CasADi usa sintaxis estándar:

print(M[:,1])
print(M[1:,1:4:2])  # 对应(start , stop , step) 

El resultado después de ejecutar es:

[00, 4, 00, 00]

[[4, 00],
 [00, 00],
 [00, 6]]

  El acceso a listas es similar (pero probablemente menos eficiente) al acceso a fragmentos:

M = SX([[3,7,8,9],[4,5,6,1]])
print(M)
print(M[0,[0,3]], M[[5,-6]])

El resultado después de ejecutar es:

[[3, 7, 8, 9],
 [4, 5, 6, 1]]
[[3, 9]] [6, 7]


1.6 Operaciones aritméticas

1.6.1 Multiplicación

  CasADi admite la mayoría de las operaciones aritméticas estándar, como suma, multiplicación, potencia, funciones trigonométricas, etc.:

x = SX.sym('x')
y = SX.sym('y',2,2)
print(sin(y)-x)

El resultado después de ejecutar es:

[[(sin(y_0)-x), (sin(y_2)-x)],
 [(sin(y_1)-x), (sin(y_3)-x)]]

  En C++ y Python (pero no en MATLAB), la operación de multiplicación estándar (usando *) todavía se usa para la multiplicación por elementos (en MATLAB .*). Para la multiplicación de matrices, use A @ B o (mtimes(A,B) en Python 3.4+):

print(y*y, y@y)

El resultado después de ejecutar es:

[[sq(y_0), sq(y_2)],
 [sq(y_1), sq(y_3)]]
[[(sq(y_0)+(y_2*y_1)), ((y_0*y_2)+(y_2*y_3))],
 [((y_1*y_0)+(y_3*y_1)), ((y_1*y_2)+sq(y_3))]]

Por convención en MATLAB, la multiplicación usando * y .* es equivalente cuando cualquiera de los argumentos es un escalar.

1.6.2 transponer

  La transposición se forma usando la sintaxis AT en Python, AT() en C++ y A o A. EnMATLAB:

print(y)
print(y.T)

El resultado después de ejecutar es:

[[y_0, y_2],
 [y_1, y_3]]

[[y_0, y_1],
 [y_2, y_3]]

1.6.3 remodelar()

  Reformar significa cambiar el número de filas y columnas pero conservando el número de elementos y las posiciones relativas de los elementos distintos de cero. Esta es una operación muy económica desde el punto de vista computacional y se realiza utilizando la siguiente sintaxis:

x = SX.eye(4)
print(reshape(x,2,8))

El resultado después de ejecutar es:

@1=1,
[[@1, 00, 00, 00, 00, @1, 00, 00],
 [00, 00, @1, 00, 00, 00, 00, @1]]

1.6.4 vertcat()/horzcat()

  La concatenación significa apilar matrices horizontal o verticalmente. Debido a la forma de columnas principales de almacenar elementos en CasADi, las matrices apiladas horizontalmente son las más eficientes. Las matrices que en realidad son vectores de columna (es decir, que constan de una sola columna) también se pueden apilar verticalmente de manera eficiente. Realice uniones verticales y horizontales usando las funciones vertcat y horzcat en Python y C++ (tomando un número variable de argumentos de entrada) y usando corchetes en MATLAB:

x = SX.sym('x',5)
y = SX.sym('y',5)
print(vertcat(x,y))

El resultado después de ejecutar es:

[x_0, x_1, x_2, x_3, x_4, y_0, y_1, y_2, y_3, y_4]

print(horzcat(x,y))

El resultado después de ejecutar es:

[[x_0, y_0],
 [x_1, y_1],
 [x_2, y_2],
 [x_3, y_3],
 [x_4, y_4]]

  También existen variaciones de estas funciones que toman como entrada una lista (en Python) o una matriz de celdas (en Matlab):

L = [x,y]
print(hcat(L))

El resultado después de ejecutar es:

[[x_0, y_0],
 [x_1, y_1],
 [x_2, y_2],
 [x_3, y_3],
 [x_4, y_4]]

1.6.5 división

  La división horizontal y vertical son las operaciones inversas de la concatenación horizontal y vertical presentada anteriormente. Para dividir una expresión horizontalmente en n expresiones más pequeñas, debe proporcionar un desplazamiento vectorial de longitud n+1 además de la expresión que se va a dividir. El primer elemento del vector de desplazamiento debe ser 0 y el último elemento debe ser el número de columna. Los elementos restantes deben estar en orden no decreciente. Entonces, la salida i de la operación de división contiene offset[i]≤c<offset[i+1] con offset[i]≤c<offset[i+1]de fs e t [ i ] _ _C<de f s e t [ i _+1 ] columna c. La sintaxis se demuestra a continuación:

x = SX.sym('x',5,2)
w = horzsplit(x,[0,1,2])
print(w[0], w[1])

El resultado después de ejecutar es:

[x_0, x_1, x_2, x_3, x_4] [x_5, x_6, x_7, x_8, x_9]

  La operación vertsplit funciona de manera similar, pero los vectores de desplazamiento se refieren a filas:

w = vertsplit(x,[0,3,5])
print(w[0], w[1])

El resultado después de ejecutar es:

[[x_0, x_5],
 [x_1, x_6],
 [x_2, x_7]]
[[x_3, x_8],
 [x_4, x_9]]

  Para la división vertical anterior, puede utilizar el acceso a fragmentos en lugar de divisiones horizontales y verticales:

w = [x[0:3,:], x[3:5,:]]
print(w[0], w[1])

El resultado después de ejecutar es:

[[x_0, x_5],
 [x_1, x_6],
 [x_2, x_7]]
[[x_3, x_8],
 [x_4, x_9]]

  Para las variables creadas por SX, esta alternativa es completamente equivalente, pero para los gráficos MX es mucho más eficiente usar horzsplit/vertsplit cuando se necesitan todas las expresiones de división.

1.6.6 Producto interno

  内积,定义为< A , B > : = tr ( AB ) = ∑ i , j A i , j B i , j <A,B>:=tr(AB)=∑_{i,j}A_{ i,j}B_{i,j}<un ,B>:=t r ( A B )=yo , jAyo , jByo , j, creado de la siguiente manera:

x = SX.sym('x',2,2)
print(dot(x,x))

El resultado después de ejecutar es:

(((cuadrado(x_0)+cuadrado(x_1))+cuadrado(x_2))+cuadrado(x_3))

  Muchas de las operaciones anteriores también se definen para clases dispersas, y las matrices devueltas después de operaciones como vertcat, horzsplit, transposición, suma (devuelve la unión de dos patrones dispersos) y multiplicación (devuelve la intersección de dos patrones dispersos) también se definen para clases dispersas. escaso.

1.7 Atributos de consulta

  Puede comprobar si una matriz o un patrón disperso tiene una propiedad específica llamando a la función miembro adecuada. Por ejemplo, consulte el tamaño de la matriz:

y = SX.sym('y',10,1)
print(y.shape)

El resultado después de ejecutar es:

(10, 1)

  Las operaciones comúnmente utilizadas para consultar los atributos de una matriz A incluyen las siguientes:

Nombre de la función Función
A.tamaño1() Número de líneas
A.tamaño2() Número de columnas
Una forma ("tamaño" en MATLAB), es decir, el par (nrow, ncol )
Un nombre() El número de elementos, es decir, nrow*ncol
A.nnz() El número de elementos distintos de cero en la estructura, si es denso, es igual a A.numel().
A. escasez() Recuperar una referencia al modo disperso
A.is_dense() es una matriz densa, es decir, no tiene ceros estructurales
A.is_scalar() ¿Es la matriz escalar, es decir, tiene dimensiones 1×1?
A.is_column() ¿Una matriz es un vector, es decir, las dimensiones son n a 1?
A.is_square() ¿Es la matriz una matriz cuadrada?
A.is_triu() ¿Es una matriz triangular superior?
A.is_constant() ¿Son constantes todas las entradas de la matriz?
A.is_integer() 矩阵项都是整数值吗?

1.8 线性代数

  CasADi 支持有限数量的线性代数运算,例如 对于线性方程组的解:

A = MX.sym('A',3,3)
b = MX.sym('b',3)
print(solve(A,b))

运行后输出结果为:

(A\b)

1.9 微积分 - 算法微分

  CasADi 最核心的功能是algorithmic(or automatic)微分 (AD)。 对于函数 f : R N → R M f:\mathbb{R}^N→\mathbb{R}^M f:RNRM:
y = f ( x ) , y=f(x), y=f(x),
前向模式方向导数(forward mode directional derivatives)可用于计算 Jacobian-times-vector 乘积:

y ^ = ∂ f ∂ x x ^ \hat{y} = \frac{\partial f}{\partial x} \hat{x} y^=xfx^
类似地,反向模式方向导数(reverse mode directional derivatives)可用于计算雅可比转置时间向量乘积:
x ^ = ( ∂ f ∂ x ) T y ^ \hat{x} = (\frac{\partial f}{\partial x})^T \hat{y} x^=(xf)Ty^

  正向和反向模式方向导数的计算成本与评估 f(x) 成正比,而与 x 的维数无关。

  CasADi 还能够有效地生成完整的、稀疏的雅可比行列式。 其算法非常复杂,但基本上包括以下步骤:

  • 自动检测 Jacobian 的稀疏模式
  • 使用图着色技术找到构建完整雅可比行列式所需的一些前向和/或方向导数
  • 以数字或符号方式计算方向导数
  • 计算雅可比行列式

Hessian 的计算方法是首先计算梯度,然后执行与上述相同的步骤,以与上述相同的方式计算梯度的雅可比矩阵,同时利用对称性。

1.9.1 句法

  计算雅可比行列式的表达式:

A = SX.sym('A',3,2)
x = SX.sym('x',2)
print(jacobian(A@x,x))

运行后输出结果为:

[[A_0, A_3],
 [A_1, A_4],
 [A_2, A_5]]

  当微分表达式为标量时,还可以计算矩阵意义上的梯度:

print(gradient(dot(A,A),A))

运行后输出结果为:

[[(A_0+A_0), (A_3+A_3)],
 [(A_1+A_1), (A_4+A_4)],
 [(A_2+A_2), (A_5+A_5)]]

请注意,与 jacobian 不同,梯度始终返回一个密集向量。

Hessians 和作为副产品的梯度计算方法如下:

[H,g] = hessian(dot(x,x),x)
print('H:', H)

运行后输出结果为:

H: @1=2,
[[@1, 00],
 [00, @1]]

  对于计算雅可比乘法向量乘积,jtimes 函数——执行前向模式 AD——通常比创建完整雅可比矩阵和执行矩阵向量乘法更有效:

A = DM([[1,3],[4,7],[2,8]])
x = SX.sym('x',2)
v = SX.sym('v',2)
f = mtimes(A,x)
print(jtimes(f,x,v))

运行后输出结果为:

[(v_0+(3v_1)), ((4v_0)+(7v_1)), ((2v_0)+(8*v_1))]

jtimes 函数可选地计算转置雅可比次向量乘积,即反向模式 AD:

w = SX.sym('w',3)
f = mtimes(A,x)
print(jtimes(f,x,w,True))

运行后输出结果为:

[(((2w_2)+(4w_1))+w_0), (((8w_2)+(7w_1))+(3*w_0))]

Supongo que te gusta

Origin blog.csdn.net/qq_16775293/article/details/117422579
Recomendado
Clasificación