Search code examples
pythondataframevariablespyomo

Accessing pyomo variables with two indices


I have started using pyomo to solve optimization problems. I have a bit of an issue regarding accessing the variables, which use two indices. I can easily print the solution, but I want to store the index depending variable values within a pd.DataFrame to further analyze the result. I have written following code, but it needs forever to store the variables. Is there a faster way?

df_results = pd.DataFrame()
df_variables = pd.DataFrame()

results.write()
instance.solutions.load_from(results)

for v in instance.component_objects(Var, active=True):
    print ("Variable",v)
    varobject = getattr(instance, str(v))

    frequency = np.empty([len(price_dict)])

    for index in varobject:
        exist = False
        two = False
        if index is not None:
            if type(index) is int:
                #For time index t (0:8760 hours of year)
                exists = True #does a index exist
                frequency[index] = float(varobject[index].value)
            else:
                #For components (names)
                if type(index) is str:
                    print(index)
                    print(varobject[index].value)
                else:
                    #for all index with two indices
                    two = True #is index of two indices
                    if index[1] in df_variables.columns:
                        df_variables[index[0], str(index[1]) + '_' + str(v)] = varobject[index].value
                    else:
                        df_variables[index[1]] = np.nan
                        df_variables[index[0], str(index[1]) + '_' + str(v)] = varobject[index].value

        else:
            # If no index exist, simple print the variable value
            print(varobject.value)

        if not(exists):
            if not(two):
                df_variable = pd.Series(frequency, name=str(v))
                df_results = pd.concat([df_results, df_variable], axis=1)
                df_variable.drop(df_variable.index, inplace=True)
            else:
                df_results = pd.concat([df_results, df_variable], axis=1)
                df_variable.drop(df_variable.index, inplace=True)

Solution

  • with some more work and less DataFrame, I have solved the issue with following code. Thanks to BlackBear for the comment

        df_results = pd.DataFrame()
        df_variables = pd.DataFrame()
    
        results.write()
        instance.solutions.load_from(results)
    
        for v in instance.component_objects(Var, active=True):
            print ("Variable",v)
            varobject = getattr(instance, str(v))
    
            frequency = np.empty([20,len(price_dict)])
    
            exist = False
            two = False
    
            list_index = []
            dict_position = {}
            count = 0
    
            for index in varobject:
                if index is not None:
                    if type(index) is int:
                        #For time index t (0:8760 hours of year)
                        exist = True #does a index exist
                        frequency[0,index] = float(varobject[index].value)
                    else:
                        #For components (names)
                        if type(index) is str:
                            print(index)
                            print(varobject[index].value)
                        else:
                            #for all index with two indices
                            exist = True
                            two = True #is index of two indices
                            if index[1] in list_index:
                                position = dict_position[index[1]]
                                frequency[position,index[0]] = varobject[index].value
                            else:
                                dict_position[index[1]] = count
                                list_index.append(index[1])
                                print(list_index)
                                frequency[count,index[0]] = varobject[index].value
                                count += 1
                else:
                    # If no index exist, simple print the variable value
                    print(varobject.value)
    
            if exist:
                if not(two):
                    frequency = np.transpose(frequency)
                    df_variable = pd.Series(frequency[:,0], name=str(v))
                    df_results = pd.concat([df_results, df_variable], axis=1)
                    df_variable.drop(df_variable.index, inplace=True)
                else:
                    for i in range(count):
                        df_variable = pd.Series(frequency[i,:], name=str(v)+ '_' + list_index[i])
                        df_results = pd.concat([df_results, df_variable], axis=1)
                        df_variable.drop(df_variable.index, inplace=True)