=======================
 coopr.pyomo CHANGELOG
=======================

-------------------------------------------------------------------------------
 2.3
-------------------------------------------------------------------------------

- Misc rework of the scripting modules. These changes allow this
  functionality to be used more effectively within other Python scripts.

- Added the 'include' command, which can include other *.dat files. This
  works like the AMPL include command, with the exception that it must
  be terminated by a semicolon.

- Reworked the AMPL datafile plugin to simple execute an include command
  on a *.dat file. This rework has the advantage that filename/lineno
  information is now propigated throught he AMPL command processing.

- Reworked the parsing of data command files (formerly known
  as AMPL DAT files). This rework is the first step towards a full
  parse of these files. I've used PLY to lex/yacc these files. This
  should resolve a variety of issues that we've observed relating to the
  sensitivity of the old parser to whitespace. 

- Added an 'import' command to integrate data from external sources 
  (plain text, csv, spreadsheets, etc)

- Added suffix option to pyomo script, to enable specification of
  suffixes on the command-line.

- Renaming the 'presolve' phase in Pyomo to 'preprocess'. We'll
  eventually want an explicit presolve phase, but that will be applied
  as a transformation, right before the problem is written and sent to
  the solver. Currently, this preprocess phase collects data about the
  model and computes the canonical representations for expressions.

- Created the ability to support the construction of concrete models.
  The concrete_mode() method for Model objects enables this mode.
  When in the concrete mode, each component added to the model has
  its construct() method called immediately after the component is
  added to the model. The symbolic_mode() method for Model objects
  can be called to switch back to a symbolic mode (which defers the
  execution of construct().

  Bad things might happen if you switch back and forth between these
  modes. Notably, if you ever generate components in symbolic mode,
  then you need to switch back to symbolic mode before calling create().

  Note that the Model.create() method is still called when the model
  construction is 'done', even when done completely in concrete mode.
  This basically calls the preprocessing steps, and this method returns
  the current model (i.e. no cloning is done when building a concrete
  model).

- Enhanced the API for ordered sets.

- Misc portability fixes.

- Significantly improved performance of PyomoModel? _clear_attribute
  method, mainly by eliminate unnecessary calls to it through setattr_exec

- Fixed issue with LP format writer involving the failure to output model
  prefixes for the constant-offset term. Only impacts the PySP EF writer -
  eliminates a warning from CPLEX, and an error report from GLPK.

- Extended the Pyomo parser to allow for the specification of namespaces 
  in data command files.

- Bug fix: recognize when bounds are constant expressions, and
  print their value.

-------------------------------------------------------------------------------
 2.2
-------------------------------------------------------------------------------

- Reworked the ModelData logic to use plugins to load data from different
  sources.

- Reworked the canonical expression definition to include a dictionary
  from variable ID -> _VarValue

- Added ability to process multiple *.dat files on the Pyomo command line

- Suppressed warning for 'constrant constraint' when writing LP files.

- A rework of the NL/LP file writers. This now uses the
  canonical expression representation. 

- Allowed PyomoModel to load results with 'Warning' status

- Cut the runtime of the PyomoModel._load_solution method by 2/3.

- Added pyomo2lp and pyomo2nl commands.

- Refactored the pyomo command-line script to make it easier to write 
  related scripts.

- Setup a draft implementation of expressions for intrinsic functions.

- Changed the setitem interface for the parameter and variable base class 
  to allow invocations of the following form:

    var[None] = some_value

  In cases where the variable Var is a singleton, i.e., non-indexed. This slight
  abuse of syntax is extremely useful in PH (and anywhere else where we have
  automated manipulation of variable values), as it avoids various if-then statements.

- Adding the @set_options decorator, which can be used
  to specify options for temporary sets that are defined by
  index functions.

- Added methods to clear objective/constraint data.

- Changes to make the API for Model() functions/attributes by
  1-based indexing. This wound up having very little impact on the
  Pyomo code base, though it has a bigger impact on my implementation of the FDT
  heuristic.

- Added xsequence(), which mimics xrange().

- Allow expressions to be generated from a dictionary variable-id ->
  _VarValue  

- Added fix to update Model statistics after a transformation.

- Adding a sequence() function, which is analogous to range()
  for generating 1-indexed sequences.

-------------------------------------------------------------------------------
 2.1
-------------------------------------------------------------------------------

- Removed some TBD notes in the Benders example, and checked in the full
  benders script (a debug version was committed initially, that only
  dealt with iteration 1). This version replicates, to within precision,
  the AMPL execution. Should terminate in 5 master iterations.

- Misc rework of variable presolving. Now, model statistics are
  stored in a more obvious location, and using more verbose names.

- Added functions that can (1) extract a canonical representation
  from an expressions, and (2) generate an expression from a canonical
  representation.

- Adding ability to load a list or tuple of values into a Pyomo
  model. These are loaded into the variables in the order in which the
  variables are identified.

- Updated variable naming. Special symbols are mapped to
  a name that contains _Q#_, where # the ASCII decimal representation
  for that symbol.

- Added support for denoting constraint inequalities as 'strict'. Added
  tests to verify that strict inequalities are recognized.

- Resolved #3970. When a parameter is specified with a default
  value, we should be able to refer to its index set directly, since
  all values are tacitly defined.

- Added a 'random' solver for the p-median example.

- Added ".solver-mipgap" option to the pyomo script, mirroring recent useful
  updates to the PH script.

- Simplified the syntax for adding a constraint to a Constraint object.

- Reworking how components interact with models. Now, components can
  only be initialized using data from the model that they are associated
  with.  Thus, models and components are tightly coupled. This allows
  the following syntax:

    model.x = Param(model.A)
    model.construct()

  The construction process uses the model data that is associated with
  the parameter. Also, this commmit allows models to be components of
  another model:

    m1=Model()
    m2=Model()
    m2.m1 = m1

  Note, however, that model construct is required to be done
  separately. When model m2 is constructed, the m1 component is not
  constructed.

- Added check to avoid printing an objective with an empty linear sum.

- Rework of the amplbook2 examples, and other Pyomo examples.

- A change in semantics for setting up dimen and dim. This change requires
  that users specify dimen in situtations where it is not obvious from the
  component declaration. For example, if you initialize from a function,
  then you'll need to specify dimen if the function returns n-tuples.

- Added an extension point for plugins that suport model transformations.
  Two transformations have been defined:  a transformation for eliminating
  fixed variables, and a transformation for relaxing integrality.  These 
  can be generically accessed with the apply_transformation() function.

- Extended API of the PyomoModel class to add a variety of helper
  functions (e.g. accessing constraints, variables and objectives).
  Adding a method for getting the model solution, as a vector.

- Added tests to exercise the Pyomo command-line.

- Updates to Pyomo command-line options:

  Added --model-name option, which allows the specification of an object
  other than 'model' for the model that is optimized.

  Added support for create_model(), which accepts a dictionary or
  pyutilib.misc.Container object containing the options specified with the
  --model-options option. This function returns a model that is optimized.

  Added the 'errors' debugging mode. When specified, exceptions dump
  a traceback. Otherwise, exceptions are caught and only the exception
  string is printed.

- Adding support for component index deactivation.  This supports the
  following semantics:

    model.C = Constraint(model.A)
    model.C[index].deactivate()

  Note that the current implementation requires the user to query whether
  each index is active:

    if model.C[index].active:
        # Do something

  I could have alternatively changed the iterator for the constraint,
  but then that could mask the existence of a constraint, making it
  difficult to reactivate.

  Finally, note that this activation mechanism is independent
  of the component level activation/deactivation:

    model.C.deactivate()
    # All C constraints are deactivated
    model.C[index].deactivate
    # You can still manipulate the C constraint
    model.C.activate()
    # Now, the C constraint is active, except for the '
    # 'index' constraint

- A rework of component management in Pyomo.  Component types are now
  managed with the natural class types (e.g.  Var for variables, rather
  than _VarBase). Further, the components should now be accessed with
  model methods: components() or active_components().  For example,

    model.components(Var)

  returns a dictionary of the Var components.

- Created the ComponentBase class, which manages the initialization of
  components. This consolidates the mechanism needed to generalize
  the component indexing operations.

- Reworking SetArray constructor to create temporary set objects for non-set
  index arguments. These arguments are passed into a Set object
  with the 'initialize' argument.

- Extended the constraint generation logic to evaluate whether the
  constraint expression contains constant values. This extension allows
  the following types of constraints to be specified:

    def f(model)
        return 0 < model.x

    def g(model)
        return model.x == model.y

    def h(model)
        return model.y > model.z

  However, it's pretty clear now that the following cannot be supported in
  Python:

    def j(model)
        return 0 < model.x < 1

  To add upper and lower bounds, a user will need to return a tuple value:

    def j(model)
        return (0, model.x, 1)

  or return an expression that is generated incrementally:

    def j(model)
        e = 0 < model.x
        return e < 1

- Significantly changed - and improved - the handling of variable lower
  and upper bounds.  In the old version of pyomo, if parameters were
  supplied as bounds, the lb/ub were silently ignored when writing
  LP/NL/etc files.

  In the new version of pyomo, these parameters are stored and handled
  to avoid this issue. In particular, the "lb" and "ub" attributes
  of a variable are either (1) None, (2) a NumericConstant?, or (3) a
  _ParamBase. The latter two objects share the common () operator. Thus,
  to access the lb and ub attributes of a variable, one should either
  test for None, or use lb() or ub() to extract the value.

- Added constraint symbol maps when writing NL files, so the constraint names
  can be mapped back (e.g., when dealing with dual variables in SOL files)
  into the user-recognized names.

-------------------------------------------------------------------------------
 2.0
-------------------------------------------------------------------------------

- Initial release of Coopr to create the coopr.pyomo package.

- See coopr.dist for previous ChangeLog information related to Coopr.

