# ___________________________________________________________________________
#
# Pyomo: Python Optimization Modeling Objects
# Copyright (c) 2008-2024
# National Technology and Engineering Solutions of Sandia, LLC
# Under the terms of Contract DE-NA0003525 with National Technology and
# Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
# rights in this software.
# This software is distributed under the 3-clause BSD License.
# ___________________________________________________________________________
import os
import subprocess
import pyomo.common
from pyomo.common.errors import ApplicationError
from pyomo.common.tempfiles import TempfileManager
from pyomo.opt.base import ProblemFormat, ConverterError
from pyomo.opt.base.convert import ProblemConverterFactory
[docs]
@ProblemConverterFactory.register('glpsol')
class GlpsolMIPConverter(object):
[docs]
def can_convert(self, from_type, to_type):
"""Returns true if this object supports the specified conversion"""
#
# Test if the glpsol executable is available
#
if not pyomo.common.Executable("glpsol"):
return False
#
# Return True for specific from/to pairs
#
if from_type == ProblemFormat.mod and to_type == ProblemFormat.cpxlp:
return True
if from_type == ProblemFormat.mod and to_type == ProblemFormat.mps:
if not pyomo.common.Executable("ampl"):
#
# Only convert mod->mps with ampl
#
return True
return False
[docs]
def apply(self, *args, **kwargs):
"""Convert an instance of one type into another"""
if not isinstance(args[2], str):
raise ConverterError("Can only apply glpsol to convert file data")
_exec = pyomo.common.Executable("glpsol")
if not _exec:
raise ConverterError("The 'glpsol' executable cannot be found")
cmd = [_exec.path(), "--math"]
#
# MPS->LP conversion is ignored in coverage because it's not being
# used; instead, we're using pico_convert for this conversion
#
modfile = ''
if args[1] == ProblemFormat.mps: # pragma:nocover
ofile = TempfileManager.create_tempfile(suffix='.glpsol.mps')
cmd.extend(
[
"--check",
"--name",
"MPS model derived from " + os.path.basename(args[2]),
"--wfreemps",
ofile,
]
)
elif args[1] == ProblemFormat.cpxlp:
ofile = TempfileManager.create_tempfile(suffix='.glpsol.lp')
cmd.extend(
[
"--check",
"--name",
"MPS model derived from " + os.path.basename(args[2]),
"--wcpxlp",
ofile,
]
)
if len(args[2:]) == 1:
cmd.append(args[2])
else:
#
# Create a temporary model file, since GLPSOL can only
# handle one input file
#
modfile = TempfileManager.create_tempfile(suffix='.glpsol.mod')
OUTPUT = open(modfile, "w")
flag = False
#
# Read the model file
#
INPUT = open(args[2])
for line in INPUT:
line = line.strip()
if line == "data;":
raise ConverterError(
"Problem composing mathprog model and data files - mathprog file already has data in it!"
)
if line != "end;":
OUTPUT.write(line + '\n')
INPUT.close()
OUTPUT.write("data;\n")
#
# Read the data files
#
for file in args[3:]:
INPUT = open(file)
for line in INPUT:
line = line.strip()
if line != "end;" and line != "data;":
OUTPUT.write(line + '\n')
INPUT.close()
OUTPUT.write("end;\n")
OUTPUT.close()
cmd.append(modfile)
subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if not os.path.exists(ofile): # pragma:nocover
raise ApplicationError("Problem launching 'glpsol' to create " + ofile)
if os.path.exists(modfile):
os.remove(modfile)
return (ofile,), None # empty variable map