es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo crear un Param con tamaño variable en Pyomo?

Soy nuevo en Pyomo y hay una matriz similar a un array de NumPy np.array([[1,2,3,4],[5,6,7,8]...]) que representa las trayectorias predichas (posición) de los vehículos circundantes, y la primera dimensión representa el número de vehículos circundantes, la segunda dimensión representa el horizonte predicho.

Como uso Pyomo para calcular la acción del vehículo ego en cada paso de tiempo, y el número de vehículos circundantes cambia en cada paso de tiempo, la forma de la primera dimensión de la matriz siempre está cambiando, y estas trayectorias predichas se utilizan para calcular la función objetivo, como obj = Σx, donde x representa la trayectoria predicha, el número de vehículos circundantes determina el número de elementos. Por ejemplo, ahora hay 2 vehículos circundantes, obj = x0+x1, en el siguiente paso de tiempo, hay 3 vehículos circundantes, por lo que obj = x0+x1+x2. Así que me pregunto cómo crear un Param con RangeSet modificable y colocar la matriz de NumPy de 2 dimensiones modificable en el Param, o si hay algún otro método para combinar la función objetivo con la entrada cambiante.

Mi idea es la siguiente:

m = ConcreteModel()
m.num = Param(RangeSet(0,0),default= 0, mutable=True)
m.x = Param(RangeSet(0,value(m.num[0])-1),RangeSet(0,3), mutable=True)

x0 = np.array([[1,2,3,4],[5,6,7,8]])
m.num.reconstruct({0:x0.shape[0]})
m.x.reconstruct()
m.pprint()

pero la forma de m.x no cambia:

1 Set Declarations
    x_index : Size=1, Index=None, Ordered=True
        Key  : Dimen : Domain              : Size : Members
        None :     2 : x_index_0*x_index_1 :    0 :      {}

3 RangeSet Declarations
    num_index : Dimen=1, Size=1, Bounds=(0, 0)
        Key  : Finite : Members
        None :   True :     [0]
    x_index_0 : Dimen=1, Size=0, Bounds=(None, None)
        Key  : Finite : Members
        None :   True :      []
    x_index_1 : Dimen=1, Size=4, Bounds=(0, 3)
        Key  : Finite : Members
        None :   True :   [0:3]

2 Param Declarations
    num : Size=1, Index=num_index, Domain=Any, Default=0, Mutable=True
        Key : Value
          0 :     2
    x : Size=0, Index=x_index, Domain=Any, Default=None, Mutable=True
        Key : Value

6 Declarations: num_index num x_index_0 x_index_1 x_index x

Tal vez mi método está bastante equivocado, agradezco sinceramente cualquier ayuda.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para lograr la funcionalidad deseada de cambiar la forma de un Param de Pyomo con un RangeSet indexado por el número de vehículos circundantes, puedes utilizar el siguiente enfoque:

    import numpy as np
    from pyomo.environ import *
    
    m = ConcreteModel()
    
    # Define el parámetro mutable para el número de vehículos circundantes
    m.num_vehicles = Param(within=NonNegativeIntegers, mutable=True)
    
    # Define la forma inicial del arreglo
    x0 = np.array([[1,2,3,4],[5,6,7,8]])
    
    # Define la forma del arreglo como una tupla y los datos como un arreglo de 1 dimensión
    shape = x0.shape
    data = x0.flatten()
    
    # Define el RangeSet que depende del parámetro mutable
    rs = RangeSet(0, m.num_vehicles-1)
    
    # Define el parámetro mutable que tiene un RangeSet dependiente del número de vehículos circundantes
    m.x = Param(rs, RangeSet(0, shape[1]-1), initialize=0, mutable=True)
    
    # Reconstruye los parámetros mutables cada vez que cambie el número de vehículos circundantes
    def reconstruct_params(m):
        new_shape = (m.num_vehicles(), shape[1])
        new_data = np.resize(data, m.num_vehicles() * shape[1])
        m.x.reconstruct(dict(enumerate(new_data.reshape(new_shape).tolist())))
    m.num_vehicles = 2
    reconstruct_params(m)
    m.num_vehicles = 3
    reconstruct_params(m)
    
    # Imprime los parámetros para verificar sus valores
    m.x.pprint()
    

    En este enfoque, el parámetro x se crea con un RangeSet que depende del número de vehículos circundantes. Además, se define una función reconstruct_params que actualiza la forma y los valores del parámetro x cada vez que cambia el número de vehículos circundantes. Para actualizar el parámetro x, los datos se remodelan como un arreglo de 2 dimensiones y luego se aplana a un arreglo de 1 dimensión, que luego se redimensiona según el nuevo número de vehículos circundantes y la forma original. Finalmente, se utiliza el método reconstruct para actualizar los valores del parámetro indexados por las nuevas claves de RangeSet.

    Para utilizar el parámetro x en una función objetivo, puedes definir la función objetivo como una función de Python que tome el parámetro x y el número de vehículos circundantes como argumentos, y devuelve una expresión de Pyomo. Por ejemplo:

    # Define una función de Python para la función objetivo
    def obj_fn(x, num_vehicles):
        rs = RangeSet(0, num_vehicles-1)
        return sum(x[i,j] for i in rs for j in RangeSet(0, shape[1]-1))
    
    # Agrega la función objetivo al modelo de Pyomo
    m.obj = Objective(expr=obj_fn(m.x, m.num_vehicles))
    

    De esta manera, puedes actualizar dinámicamente la forma y los valores del parámetro x y utilizarlo en una función objetivo que depende del número de vehículos circundantes.

Comments are closed.