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

-------------------------------------------------------------------------------
 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.

