Package: pyaugmecon
An AUGMECON based multi-objective optimization solver for PyomoThis is aPythonandPyomobased implementation of the augmented ε-constraint (AUGMECON) method and its variants which can be used to solve multi-objective optimization problems, i.e., to return an approximation of the exact Pareto front.It currently supports:Inner loop early exit (AUGMECON)Bypass coefficient (AUGMECON2)Flag array (AUGMECON-R)Processs-based parallelizationGAMS implementationsof the method and its variants were provided by the authors of the papers. To the best of our knowledge, this is the first publicly availablePythonimplementation.ContentsInstallationUsageTestsUseful resourcesNotesKnown limitationsInstallationPyAUGMECON can be installed fromPyPIusingpip install pyaugmecon. Detailed installation instructions for bothAnacondaandPyPIinstallations are available below.RequirementsPythonPyomoNumpyPandasCloudpicklePymooGurobi(other sovlers supported as well)TheGurobi Python bindingsare significantly faster than using the executable. So even if you have already installed Gurobi, please still install the Python version for an optimal experience.Anaconda installation (advised)This installation is advised as the PyPI installation of Gurobi does not include the licensing tools. Only Gurobi needs to be installed as other tools are by default included in Anaconda or will be automatically installed as dependencies of PyAUGMECON.# Install Anaconda from https://www.anaconda.com# Install Gurobicondaconfig--addchannelshttp://conda.anaconda.org/gurobi
condainstallgurobi# Install PyAUGMECON, and dependenciespipinstallpyaugmeconPyPI installationFor a PyPI installation, only Gurobi needs to be installed, other requirements will automatically be installed as dependencies of PyAUGMECON. As mentioned above, the PyPI version of Gurobi does not include licensing tools, seeGurobi documentationon how to install these.# Install Gurobi, PYAUGMECON, and dependenciespipinstallgurobipypyaugmeconOther solversThe installation instructions above describe an installation with Gurobi, since this is the solver that has been used for testing. However, other solvers should work as well. The only requirement is that the solver is supported by Pyomo. An example of the GLPK solver can be foundin the test folder.UsageFirst, an optimization model generator function needs to be created to pass the model to PyAUGMECON. This function should return an unsolved instance of the optimization problem, seePyomo model. Essentially, the only difference in comparison with creating a single objective Pyomo optimization model is the fact that multiple objectives are defined using Pyomo'sObjectiveList().The rest of the process is automatically being taken care of by instantiating aPyAugmecon()object and solving it afterward withPyAugmecon.solve().PyAugmecon parametersInstantiating aPyAugmecon(model, opts, solver_opts)object requires the following parameters:NameDescriptionRequiredmodelFunction that returns an unsolved instance of the optimization problem, seePyomo modelYesoptsDictionary of PyAUGMECON related options, seePyAugmecon optionsYessolver_optsDictionary of solver (Gurobi) options, seesolver optionsNoExample 3kp40The following snippet shows how to solve the3kp40model from thetestsfolder:frompyaugmeconimportPyAugmeconfromtests.optimization_modelsimportthree_kp_model# Multiprocessing requires this If statement (on Windows)if__name__=="__main__":model_type="3kp40"# AUGMECON related optionsopts={"name":model_type,"grid_points":540,"nadir_points":[1031,1069],}pyaugmecon=PyAugmecon(three_kp_model(model_type),opts)# instantiate  PyAugmeconpyaugmecon.solve()# solve PyAugmecon multi-objective optimization problemsols=pyaugmecon.get_pareto_solutions()# get all pareto solutionspayoff=pyaugmecon.get_payoff_table()# get the payoff tabledecision_vars=pyaugmecon.get_decision_variables(sols[0])# get the decision variablesPyAugmecon methodsNameDescriptionget_pareto_solutions()Get a list of Pareto-optimal solutions (list[tuple])get_decision_variables(pareto_solution)Get a dictionary of decision variables for a given Pareto-optimal solution. Where the key represents the decision variable name and the value is a pd.Series with the values.get_payoff_table()Get the payoff table from the model.PyAugmecon attributesAfter solving the model withPyAugmecon.solve(), the following object attributes are available:NameDescriptionsolsFull unprocessed solutions, only checked for uniquenessunique_solsUnique solutions, rounded toround_decimalsand checked for uniquenessunique_pareto_solsUnique Pareto solutions, only dominant solutions, rounded toround_deicmalsand checked for uniquenessnum_solsNumber of solutionsnum_unique_solsNumber of unique solutionsnum_unique_pareto_solsNumber of unique Pareto solutionsmodel.models_solvedNumber of models solved (excluding solves for payoff table)model.infeasibilitesNumber of models solved that were infeasiblemodel.to_solveTotal number of models to solve (including payoff table)model.modelPyomo model instancemodel.payoffPayoff tablemodel.eGridpoints of p-1 objective functions that are used as constraintshv_indicatorThe hypervolume indicator of the unique Pareto solutions,see Pymoo documentationfor more detailsruntimeTotal runtime in secondsPyAugmecon solutions detailsThe solutions are stored in thesols,unique_sols, andunique_pareto_solsattributes. These differ in the following ways:solscontains all solutions, including duplicates and non-Pareto solutionsunique_solscontains all unique solutions, including non-Pareto solutionsunique_pareto_solscontains all unique Pareto solutionsThe solutions are stored dictionary, where each dictionary contains the objective values (keys) and the decision variables (values). The objective values are stored as a tuple, where the first element is the objective value of the first objective function, the second element is the objective value of the second objective function, and so on. The decision variables are stored as a dictionary, where the keys are the names of the decision variables and the values are the values of the decision variables.This is an example of theunique_pareto_solsattribute:{(3,5):{'x':pd.Series([1,2]),'y':pd.Series([2,3])},(4,4):{'x':pd.Series([3,4]),'y':pd.Series([1,2])},(5,3):{'x':pd.Series([2,4]),'y':pd.Series([1,3])},}PyAugmecon optionsThe following PyAUGMECON related options can be passed as a dictionary to the solver:OptionDescriptionDefaultnameName of the model, used in logging outputUndefinedgrid_pointsNumber of grid points (if X grid points in GAMS, X+1 grid points are needed in order to exactly replicate results)nadir_pointsIf the exact nadir points are known — these can be provided, otherwise they will be taken from the payoff tableTrueearly_exitUse inner loop early-exit (AUGMECON) — exit the inner loop when the model result becomes infeasibleTruebypass_coefficientUse bypass coefficient (AUGMECON2) — utilize slack variables to skip redundant iterationsTrueflag_arrayUse flag array (AUGMECON-R) — store early exit and bypass coefficients for upcoming iterationsTruepenalty_weightThe penalty by which other terms in the objective are multiplied, usually between10e-3and10e-61e-3nadir_ratioFor problems with three or more objective functions, the payoff table minima do not guarantee the exact nadir. This factor scales the payoff minima. By providing a value lower than one, lower bounds of the minima can be estimated1logging_folderFolder to store log files (relative to the root directory)logscpu_countSpecify over how many processes the work should be divided. Use1to disable parallelizationmultiprocessing.cpu_count()redivide_workHave processes take work from unfinished processes when their queue is emptyTrueshared_flagShare the flag array between processes. If false, each process will have its own flag arrayTrueround_decimalsThe number of decimals to which the solutions are rounded before checking for uniqueness9pickle_fileFilename of the pickledPyomomodel forcloudpicklemodel.psolver_nameName of the solver provided toPyomogurobisolver_ioName of the solver interface provided toPyomo. As theGurobi Python bindingsare significantly faster than using the executable, they are set by default. If you still prefer to use the executable, set this option toNonepythonoutput_excelCreate an excel with solver output in thelogging_foldercontaining the payoff table, e-points, solutions, unique solutions, and unique Pareto solutionsTrueprocess_loggingOutputs solution process information from sub-processes to the log file. This significantly reduces performances and does not work on Windows. Don't enable this unless necessaryFalseprocess_timeoutGracefully stops all processes afterprocess_timeoutin seconds. As processes are stopped gracefully they will be allowed to finish their assigned work and not stop exactly afterprocess_timeoutNoneSolver optionsTo solve the single-objective optimization problems generated by the AUGMECON method they are passed to Gurobi, an external solver. AllGurobi solver parameterscan be passed to Gurobi with this dictionary. Two parameters are already set by default, but can be overridden:OptionDescriptionDefaultMIPGapSee Gurobi documentation:MIPGap0.0NonConvexSee Gurobi documentationNonConvex2Pyomo modelA multi-objective Pyomo model is similar to a single-objective model, except that the objectives should be defined using Pyomo'sObjectiveList()and attached to the model by an attribute namedobj_list. Multiple example models can be found in thetestsfolder and a simple model can be found below:deftwo_objective_model():model=ConcreteModel()# Define variablesmodel.x1=Var(within=NonNegativeReals)model.x2=Var(within=NonNegativeReals)# --------------------------------------#   Define the objective functions# --------------------------------------defobjective1(model):returnmodel.x1defobjective2(model):return3*model.x1+4*model.x2# --------------------------------------#   Define the regular constraints# --------------------------------------defconstraint1(model):returnmodel.x1<=20defconstraint2(model):returnmodel.x2<=40defconstraint3(model):return5*model.x1+4*model.x2<=200# --------------------------------------#   Add components to the model# --------------------------------------# Add the constraints to the modelmodel.con1=Constraint(rule=constraint1)model.con2=Constraint(rule=constraint2)model.con3=Constraint(rule=constraint3)# Add the objective functions to the model using ObjectiveList(). Note# that the first index is 1 instead of 0!model.obj_list=ObjectiveList()model.obj_list.add(expr=objective1(model),sense=maximize)model.obj_list.add(expr=objective2(model),sense=maximize)# By default deactivate all the objective functionsforoinrange(len(model.obj_list)):model.obj_list[o+1].deactivate()returnmodelTestsTo test the correctness of the proposed approach, the following optimization models have been tested both using the GAMS and the proposed implementations:Sample bi-objective problem of the original paperSample three-objective problem of the original implementation/presentationMulti-objective multidimensional knapsack (MOMKP) problems: 2kp50, 2kp100, 2kp250, 3kp40, 3kp50, 4kp40 and 4kp50Multi-objective economic dispatch (minimize cost, emissions and unmet demand)These models can be found in thetestsfolder and run withPyTestto test for the correctness of the payoff table and the Pareto solutions. Example:pytest tests/test_3kp40.pyDespite the extensive testing, the PyAUGMECON implementation is provided without any warranty. Use it at your own risk!Useful resourcesOriginal AUGMECONG. Mavrotas, “Effective implementation of the ε-constraint methodin Multi-Objective Mathematical Programming problems,”Applied Mathematics and Computation, vol. 213, no. 2, pp. 455–465, 2009GAMS implementationImproved AUGMECON2Mavrotas and K. Florios, “An improved version of the augmented ε-constraint method (AUGMECON2) for finding the exact pareto set in multi-objective integer programming problems,”Applied Mathematics and Computation, vol. 219, no. 18, pp. 9652–9669, 2013.GAMS implementationFurther improved AUGMECON-RA. Nikas, A. Fountoulakis, A. Forouli, and H. Doukas,A robust augmented ε-constraint method (AUGMECON-R) for finding exact solutions of multi-objective linear programming problems.Springer Berlin Heidelberg, 2020, no. 0123456789.GAMS implementationOther resourcesThe following PhD thesis is also very usefulThis presentation provides a quick overviewNotesThe choice of the objective function(s) to add as constraints affects the mapping of the Pareto front. Empirically, having one of the objective functions with a large range in the constraint set tends to result in a denser representation of the Pareto front. Nevertheless, despite the choice of which objectives to add in the constraint set, the solutions belong to the same Pareto front (obviously).If X grid points in GAMS, X+1 grid points are needed in PyAUGMECON in order to exactly replicate resultsFor some models, it is beneficial to runtime to reduce the number of solver (Gurobi) threads. More details:Gurobi documentationKnown limitationsFor relatively small models (most of the knapsack problems), disablingredivide_workandshared_flagshould lead to slightly lower runtimes. This is due to the overhead of sharing the flag array between processes that don't have a shared memory space. Redividing the work results in additional models solved with duplicate solutions, leading to longer runtime. By sharing the flag array in a different way and dividing the work more smartly these limitations might be solved in the future.To parallelize the solution process, the grid is divided into blocks with a minimum length of the inner loop (number of grid points) over the processes. With fewer than three objectives, there is only one dimension to iterate over, and as such no parallelization possible. This is something that can be improved in the future.ChangelogSeeChangelogCitingIf you use PyAUGMECON for academic work, please cite the followingDOI (Zenodo).CreditThis software was developed at the Electricity Markets & Power System Optimization Laboratory (EMPSOLab),Electrical Energy Systems Group,Department of Electrical Engineering,Eindhoven University of Technology.Contributors:Wouter Bles (current version of the package)Nikolaos Paterakis (initial implementation)