# ___________________________________________________________________________ # # Pyomo: Python Optimization Modeling Objects # Copyright 2017 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. # ___________________________________________________________________________ from pyomo.core.base import Var, Param, Expression, Objective, Block, \ Constraint, Suffix from pyomo.core.expr.numvalue import native_numeric_types, is_fixed, value import logging logger = logging.getLogger('pyomo.core') valid_expr_ctypes_minlp = {Var, Param, Expression, Objective} valid_active_ctypes_minlp = {Block, Constraint, Objective, Suffix} # Copied from cpxlp.py: # Keven Hunter made a nice point about using %.16g in his attachment # to ticket #4319. I am adjusting this to %.17g as this mocks the # behavior of using %r (i.e., float('%r'%) == ) with # the added benefit of outputting (+/-). The only case where this # fails to mock the behavior of %r is for large (long) integers (L), # which is a rare case to run into and is probably indicative of # other issues with the model. # *** NOTE ***: If you use 'r' or 's' here, it will break code that # relies on using '%+' before the formatting character # and you will need to go add extra logic to output # the number's sign. _ftoa_precision_str = '%.17g' def ftoa(val): if val is None: return val # # Basic checking, including conversion of *fixed* Pyomo types to floats if type(val) in native_numeric_types: _val = val else: if is_fixed(val): _val = value(val) else: raise ValueError( "Converting non-fixed bound or value to string: %s" % (val,)) # # Convert to string a = _ftoa_precision_str % _val # # Remove unnecessary least significant digits. While not strictly # necessary, this helps keep the emitted string consistent between # python versions by simplifying things like "1.0000000000001" to # "1". i = len(a) try: while i > 1: if float(a[:i-1]) == _val: i -= 1 else: break except: pass # # It is important to issue a warning if the conversion loses # precision (as the emitted model is not exactly what the user # specified) if i == len(a) and float(a) != _val: logger.warning( "Converting %s to string resulted in loss of precision" % val) # return a[:i]