3
$\begingroup$

I have a variable in Pyomo called model.variable_objectiveCosts and I would like to print this value to a file. Basically it works. But when I would like to divide the value by 100 and then round to 2 decimal digits, I get an error when using the following code "%.2f" % model.variable_objectiveCosts/100

The error message is

"TypeError: Implicit conversion of Pyomo NumericValue type `variable_objectiveCosts' to a float is
disabled. This error is often the result of using Pyomo components as
arguments to one of the Python built-in math module functions when
defining expressions. Avoid this error by using Pyomo-provided math
functions."

Now it tells me to use the Pyomo-provided math functions. However, I could not find a round function in Pyomo. Do you know how I can still round the result to 2 digits?

Here is a part of my code:

# Imports
import pyomo.environ as pyo
import pandas as pd
from pyomo.util.infeasible import log_infeasible_constraints
from pyomo.opt import SolverStatus, TerminationCondition
import sys

#Check if the problem is solved or infeasible
if (solution.solver.status == SolverStatus.ok) and (solution.solver.termination_condition == TerminationCondition.optimal):
        # Do something when the solution in optimal and feasible
        print("Result Status: Optimal")
        #Create pandas dataframe for displaying the results
        outputVariables_list = [model.variable_heatGenerationCoefficient_SpaceHeating, model.variable_heatGenerationCoefficient_DHW, model.variable_help_OnlyOneStorage, model.variable_temperatureBufferStorage, model.variable_usableVolumeDHWTank, model.variable_surplusPowerTotal, model.variable_surplusPowerPositivePart, model.variable_surplusPowerNegativePart, model.variable_help_isSurplusPowerPositive, model.variable_electricalPowerTotal, model.variable_RESGenerationTotal, model.variable_pvGeneration, model.variable_costsPerTimeSlotPositivePart, model.variable_revenuePerTimeSlotPositivePart, model.variable_currentChargingPowerEV, model.variable_energyLevelEV, model.variable_SOC_EV, model.param_heatDemand_In_W, model.param_DHWDemand_In_W, model.param_electricalDemand_In_W, model.param_pvGenerationNominal, model.param_outSideTemperature_In_C, model.param_windAssignedNominal, model.param_electricityPrice_In_Cents, model.param_availabilityPerTimeSlotOfEV, model.param_energyConsumptionEV, model.param_COPHeatPump_SpaceHeating, model.param_COPHeatPump_DHW, model.param_BigM_Surplus_Positive, model.param_BigM_Surplus_Negative, model.param_BigM_Costs_Positive, model.param_BigM_Costs_Negative, model.variable_objectiveMaximumLoad, model.variable_objectiveSurplusEnergy ,model.variable_objectiveCosts, model.objective_combined_general, model.set_timeslots]
        optimal_values_list = [[pyo.value(model_item[key]) for key in model_item] for model_item in outputVariables_list] 
        results = pd.DataFrame(optimal_values_list)
        results= results.T
        results = results.rename(columns = {0:'variable_heatGenerationCoefficient_SpaceHeating', 1:'variable_heatGenerationCoefficient_DHW', 2:'variable_help_OnlyOneStorage', 3:'variable_temperatureBufferStorage', 4:'variable_usableVolumeDHWTank', 5:'variable_surplusPowerTotal', 6:'variable_surplusPowerPositivePart', 7:'variable_surplusPowerNegativePart', 8:'variable_help_isSurplusPowerPositive', 9:'variable_electricalPowerTotal', 10:'variable_RESGenerationTotal', 11:'variable_pvGeneration', 12:'variable_costsPerTimeSlot', 13:'variable_revenuePerTimeSlot', 14:'variable_currentChargingPowerEV', 15:'variable_energyLevelEV', 16:'variable_SOC_EV', 17:'param_heatDemand_In_W', 18:'param_DHWDemand_In_W', 19:'param_electricalDemand_In_W', 20:'param_pvGenerationNominal', 21:'param_outSideTemperature_In_C', 22:'param_windAssignedNominal', 23:'param_electricityPrice_In_Cents', 24:'param_availabilityPerTimeSlotOfEV', 25:'param_energyConsumptionEV', 26:'param_COPHeatPump_SpaceHeating', 27:'param_COPHeatPump_DHW', 28:'param_BigM_Surplus_Positive', 29:'param_BigM_Surplus_Negative', 30:'param_BigM_Costs_Positive', 31:'param_BigM_Costs_Negative', 32:'variable_objectiveMaximumLoad_kW', 33:'variable_objectiveSurplusEnergy_kWH', 34:'variable_objectiveCosts_Euro', 35:'objective_combined_general', 36:'set_timeslots'})
        cols = ['set_timeslots']
    results[cols]= results [cols].round(0).astype(int)
    results.set_index('set_timeslots', inplace=True)
    results.to_csv("C:/Users/wi9632/Desktop/Result_BT1.csv", index=True,  sep =";") 
elif (solution.solver.termination_condition == TerminationCondition.infeasible):
    # Do something when model in infeasible
    print ("Result Status: Infeasible")
else:
    # Something else is wrong
    print("Solver Status: ", solution.solver.status)
$\endgroup$
11
  • $\begingroup$ If you have a line like this in your imports from pyomo.environ import * , then you should have the math functions you need for rounding. So, make sure you don't use round function from other packages (like math or numpy) or have those imports to override what pyomo is importing. $\endgroup$
    – EhsanK
    Commented Aug 16, 2021 at 12:58
  • $\begingroup$ Thanks EhasnK for your comment. How can I use the math functions to round those values in Pyomo? What command do I have to use? $\endgroup$
    – PeterBe
    Commented Aug 16, 2021 at 13:06
  • $\begingroup$ If you have the from pyomo.environ import *, then I believe the round function is already there. What I meant is to test it like that and make sure you're not rounding with np.round or math.round. This seems to be a common issue. If you do a quick search on the web, you'll see some similar questions with the same error. $\endgroup$
    – EhsanK
    Commented Aug 17, 2021 at 14:11
  • $\begingroup$ Thanks EhsanK for your answer. Unfortunately np.round(model.variable_objectiveCosts/100, 2) leads to the following error message "TypeError: loop of ufunc does not support argument 0 of type MonomialTermExpression which has no callable rint method". When just using np.round(model.variable_objectiveCosts, 2) I get a error "TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'" $\endgroup$
    – PeterBe
    Commented Aug 18, 2021 at 8:52
  • 1
    $\begingroup$ There is a lot of documentation on rounding values on the whole dataframe or just a column (series) or a single value in case you want to treat a given value differently. I'm sure you can find the appropriate command by a simple search :) $\endgroup$
    – EhsanK
    Commented Aug 18, 2021 at 13:26

1 Answer 1

2
$\begingroup$

The best way to proceed is that

  1. Let the Pyomo solve the problem
  2. Use round(value(model.OF)) ,2)
$\endgroup$
6
  • $\begingroup$ Thanks for your answer Optimizaiton team. When I use your suggested approach in my example by using the code round(pyo.value(model.variable_objectiveCosts/100) ,2) I get the error "TypeError: 'float' object is not iterable". I also tried to just adjust the values in a dataframe (because at the end of the day this is what I want) by using ` df['variable_objectiveCosts'] = df['variable_objectiveCosts'/100].round(2)` but here I get also an error message telling "TypeError: unsupported operand type(s) for /: 'str' and 'int'". Any idea how I can fix these errors? $\endgroup$
    – PeterBe
    Commented Aug 16, 2021 at 12:01
  • $\begingroup$ share your code here to be able to provide you a better answer before any thing try to print your answer can you do it in your code? print the value of your objective function $\endgroup$ Commented Aug 16, 2021 at 12:16
  • $\begingroup$ Thanks optimization team for your comment. I added a part of my code (my full code is quite complex and has 2000 lines) after the solve statement. You have to scroll to almost the very right for the variable model.variable_objectiveCosts. What I want is to print this to a file (via a pandas dataframe together with all other variables) and there it should be devided by 100 and rounded to 2 decimal values. $\endgroup$
    – PeterBe
    Commented Aug 16, 2021 at 12:38
  • $\begingroup$ @PeterBe in this piece you shared in the comment, df['variable_objectiveCosts'] = df['variable_objectiveCosts'/100].round(2) you're dividing by 100 in the brackets. that's why it gave you the TypeError. You need to bring it out df['variable_objectiveCosts']/100 $\endgroup$
    – EhsanK
    Commented Aug 16, 2021 at 12:50
  • $\begingroup$ I repeat my previous comment Please check if you can print the value of your objective function if you are successful in doing that then show me the command you used for doing so then I can help you to safe it as a panda dataframe or round it to 2 digits or divide it by 100 $\endgroup$ Commented Aug 16, 2021 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.