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

-------------------------------------------------------------------------------
 3.4
-------------------------------------------------------------------------------

- Under development.

-------------------------------------------------------------------------------
 3.3.2
-------------------------------------------------------------------------------

-  Adding additional overloads to support model generation when

      from future import division

   is in effect.

- Fix to propagate the core exception up when there is a problem reading
  from an external data source.

- Improved error message when an exception is raised outside Pyomo while
  attempting to read data from an ODBC data source.

- Do not remove temporary files if the keepfiles option has been specified.

-  Various updates to Piecewise:
  - Adding experimental support for step functions to Piecewise. 
  - Adding an optional keyword to disable warnings about coverage of the domain variable feasible region.
  - Adding an optional keyword to allow using an unbounded or partially bounded domain variable.

-------------------------------------------------------------------------------
 3.3.1
-------------------------------------------------------------------------------

- Adding some exception handling logic to handle cases where
  parameters are being initialized with data that is not a dictionary.

- Fix for newer ODBC drivers (Fedora 17).

- Slight performance optimization in Constraint.add()

- Improved error message when passing a Boolean to Constraint.add()

- Added (preliminary) support for *.xslx, *.xlsm and *.xlsb files.

-------------------------------------------------------------------------------
 3.3
-------------------------------------------------------------------------------

- Many code structural changes that are not user-visible. Includes replacement
  of _VarBase by Var, _ParamBase by Param, eliminating _BaseSet, 

- Generalized the suffix management system, which used to be isolated to Var. 
  Suffix management is now provided at the base (Sparse)IndexedComponent level.

- Introduced SparseIndexedComponent, which Param is now derived from. In the
  longer term, SparseIndexedComponent will replace IndexedComponent. The intent
  is to provide more uniform support for components with sparse index sets.
  As a result, the implementation of Param was completely overhauled.

- Fixed a major bug in the NL writer, which impacted certain types of non-linear
  models. In these cases, incorrect summary information was being written 
  to the header section of the NL file, which caused solvers like Ipopt to 
  silently converge to bogus solutions.

- Added a --report-timing option to the pyomo script, to provide detailed 
  information about how long it takes to construct each model component.

- Modified the construction rules for all pyomo objects to take the parent
  block as the first input argument, as opposed to the model. The first step
  toward a full-scale nested, block-composable capability in pyomo.

- Modified pyomo to default to using non-symbolic solver labels, e.g., x1.
  Intent is to reduce output file sizes. To restore symbolic solver label
  capability, use the --symbolc-solver-labels option on the pyomo script.

- Extensive optimization of expression generation, preprocessing, and file
  writing. No functional change, but users should notice significant (up
  to 33%) reductions in model construction and file write times. On large
  models - mileage may vary.

- Changed the default in Param from mutable=True to mutable=False. This is 
  a *big* change, although the typical user will probably not notice. The 
  motivation here is that most parameters are not modified in most optimization
  use cases, so the user is now required to specify which Params are going to
  be changed. If a user attempts to change the value of an immutable Param,
  an exception is thrown. The immutable default leads to faster expression
  generation and a lower memory footprint, due to the use of numeric 
  constants instead of individual Param objects.

- Pyomo now requires the use of "value(x)" instead of "x.value" or "x()" to 
  obtain the value of variables, parameters, or anything else that is intended 
  to be reduced / evaluated to a constant numeric value (e.g., in an constraint
  if expression). 

- Removed the identify_variables preprocessor. The functionality was 
  redundant with logic that occurs during file write (and solver interaction
  in general), and it was costly in terms of run-time.   

- Modified semantics of expressions relating to fixed/constant values. The
  is_constant() call means that an expression will always evaluate to the
  same numeric value, e.g., an immutable Param. In contrast, is_fixed()
  only guarantees (if True) that the value of the expression is *currently*
  fixed. However, it might change subsequently, e.g., in the case of 
  mutable Parms.

-------------------------------------------------------------------------------
 3.2
-------------------------------------------------------------------------------

- Many other bug fixes...

- Adding hook to parse filenames that have DriveName : FileName syntax.

- Changing tests, to clarify the fact that the test failure
  is due to the fact that model.A != model.A.value

- Removing all direct calls to the NumericConstant constructor.

- Removing ZeroConstant and OneConstant

- Converting all exception constructors to use Python 3.x-compatible syntax.

- Performance improvement in Param.py, when constructing via
  rule-based initializers. A ton of redundant index checking is
  being performed in this case, which is totally unnecessary.

- Standardizing data names: _ParamData, _ConstraintData, _VarData.

- A rework of Objective.  Segregating SOSConstraint into a separate
  file (since it's a different type of constraint component).

- Migrating indexing logic from Objective and Constraint into the
  IndexedComponent base class.

- Removed the ConstraintBase class. This is not really used now,
  and per John's suggestion the SOS and PieceWise constraints should
  be handled through transformations.

- Added tests for NaN and Infinity values.

- Adding unit tests for numeric values.

- Adding a post-processing step to the Pyomo script to calculate
  the objective(s) if they were not returned by the solver plugin
  in the results object.

- Removing processing of 'name' keyword argument from _VarBase. It
  was recently added to the Component base class. Processing it at
  the _VarBase level caused it to be set to 'unknown' in the Component
  constructor.

- Adding param tests to expose mutability issues and various other bugs.

- Finishing code review of BuildAction and BuildCheck.
  This involved migrating some logic into Component and
  cleaning up some logic in IndexedComponent.

- A first code review, focusing on Component and
  IndexedComponent. There were many changes because I changed the
  names of some component attributes to clarify what were public
  and private attributes.  A private attribute refers to an attribute
  that an end-user is not expected to use.

- Correcting sos constraint generation code in nl writer. This fixes
  a bug which caused code failure when variable indices where strings.

- Cleaning up the network_flow example.

- Fixing bug in nl writer when handling non-indexed sos constraints.

- Fixing bug in piecewise component where tuples were not completely
  flattened before being sent to function rules.

-------------------------------------------------------------------------------
 3.1
-------------------------------------------------------------------------------

- Fixed bug with error message in LP writer - referenced an unknown identifier.

- Added a few pickle tests to expose bug in NL and LP writer (ticket #4329).

- Fixed an issue with the LP writer labeler that yielded improper
  block-prefixed in the case of SOS constraints.

- A preliminary rework of the Pyomo script functions to
  declare them using the Coopr functor API.

- Pausing garbage collection in the LP writer.

- Eliminated the 'id' slot of the _VarValue class, as it is no longer used.

- Various performance tweaks and cleanup on the LP writer. 

- Updating the required syntax for f_rule and d_f_rule keywords
  passed to the Piecewise component.

- Various efficiency improvements for the DAT parser.

- Modifying LP writer to properly deal with zero-coefficient quadratic terms.

- Adding method to canonical preprocessor allowing per-constraint
  invocation, to enable fine-grained preprocessing.

-------------------------------------------------------------------------------
 3.0.1
-------------------------------------------------------------------------------

- Fixing import error when ordereddict is not available.

- More performance improvements in _VarBase constructor. Eliminated
  _add_domain_key method, which is unused.

- Some performance improvements in var.py:485(construct).


-------------------------------------------------------------------------------
 3.0
-------------------------------------------------------------------------------

- Implemented weak references in Pyomo components.

- Changes to allow expressions as variable bounds.

- Changed core interface classes to _not_ be services, so these components are
  not automatically generated.

- Added support for connecting to a database with ODBC using pyodbc.

- Added the 'coopr check' subcommand to test the logic of Pyomo models.

- Rework of SOS functionality, including exhaustive SOS tests.

- Added SQLite database example.

- Added comprehensive support for set expressions

- Comprehensive rework of blocks and connectors, which support a modular
  approach to modeling with repreated sub-models.

- Added VarList modeling component.

- Added performance tests for memory usage.

- Removed label data from all Pyomo modeling components.  The text label used
  by problem writers is now deteremined by the writers themselves.  The
  SymbolMap object is now used to map variables to results objects.

- Test results now rely on JSON format, rather than YAML.

- Reworked the implementation of RangeSet, which is now a virtual concrete
  set.

- Added pyomo2osil command.

- Removing deprecation of pre-3.0 rule order.  Models using the pre-3.0 rule
  order now generate errors rather than warnings.

-------------------------------------------------------------------------------
 2.8
-------------------------------------------------------------------------------

- Addition of SumExpression and ProductExpression checks in _get_bound,
  which will avoid "nonconstant bound" errors when sums or products of
  constants are using as constraint bounds

- Efficiency improvements in the generation of NL files.

- Significant efficiency improvements in the parsing of Pyomo Data Files.

- Addition of an 'extensive form' NL writer. If a dictionary of models
  is passed to the writer rather than just a single model, the writer
  assumes that the problem should be constructed as an EF problem.

- Added keyword 'ignore_invalid_labels' to _load_solution method of
  PyomoModel. If True, then the method will silently ignore the
  loading of any solution components whose label does not appear in the
  model. Useful in situations where results are loaded into related,
  but not identical, models.

- Changed the logic for the NL writer to ensure that files are consistently
  generated on different platforms.

- Added a special case for expression reference detection so that 
  expressions of the form:

     expr <= expr

  do not trigger an unnecessary clone within Constraint.add()

-------------------------------------------------------------------------------
 2.7
-------------------------------------------------------------------------------

- Added NL and LP writer support for ConstraintList model objects.

- Changed expected order of arguments in Pyomo model results - models
  now come first, instead of last. Failing to do this will yield a
  deprecation warning for Coopr 3.0. In Coopr 3.1, this will yield
  an error.

- Added --solver-io option to pyomo script, to allow specification of
  the interface mechanism (e.g., python or file) for solver plugins.

- Changed representation of variables in solutions from SolutionMap to
  raw Python dictionaries, yielding major performance improvements for
  large models.

- Major structural re-work of labeling mechanisms in Pyomo; no user
  impact. In preparation for elimination of labels from modeling
  components, and their migration into solver plugins and problem writers.

- Numerous performance enhancements.

- Reformatting with reindent.
- Various minor bug fixes.
- Added an extensive form NL writer and performance improvements to the current NL writer.

-------------------------------------------------------------------------------
 2.6.2
-------------------------------------------------------------------------------

- Bug fix in the update process for results objects, which is exposed when
  using suffix data.

- Changes in the output generated by the Pyomo script, to make the semantics
  of the timing clearer.

- Various efficiency improvements due to the use of fixed-positional 
  constructors.

- Fixing logic bug in _tighen_bounds method of _VarValue - if a domain
  lb/ub was equal to None and the corresponding variable lb/ub was also
  equal to None, setlb/setub were being called with None. Technically OK,
  but a waste of time.

-------------------------------------------------------------------------------
 2.6.1
-------------------------------------------------------------------------------

- Fixing serious performance error in Var constructor when variable
  bounds are supplied via a function. Due to incorrect indentation, the
  initialization loop was running in O(N2) time, rather than O(N). No
  functional change - just an incredible reduction in run-time for big
  models.

- Bugfix for pickling EqualityExpressions

- Improved tests, diagnostics, and error messages for compound inequality
  expressions.

- A change to avoid the unexpected behavior in #4224. Previously,
  when using --debug a *.lp file would be written. But that mucks with the
  instance representation, which is not good. With this change, a user
  will need to explicitly dump a model using pyomo2lp (or pyomo2nl).

- Resolving issues with #4225. As part of this change, results are always
  loaded into the model.

- Fixes for #4226. Apparently if a value is returned by a command-line
  entry point ... it then gets printed! (?)

-------------------------------------------------------------------------------
 2.6
-------------------------------------------------------------------------------

- Migrating to the use of entry points instead of explicit script installation.
  This allows for installation and localization of scripts on MS Windows.

- Fixing the symbol_map generated for LP files. This uses '[]' symbols
  rather than '()'.

- Adding formal support for in-place operators (+=, -=, *=, /=,
  **=) for NumericValue? and expressions. This resolves a significant
  performance degradation observed for engval1 and hagar2 CUTE tests
  caused by the addition of "proper" expression cloning in r3798.

- inequalities can now be specified in "compound" form (lb <= expr <= ub)
  - this goes a long way toward resolving #4150
  - there are still several edge cases where this does not work, and 
    some additional error traps and unit tests are still needed. 

- overhaul of Expression unit testing
  - moving several test suites that were not related to unit testing 
    expressions out to other test_*.py files (e.g. param, con, obj). 

- _VarBase and _ParamBase now better approximate the NumericValue? API 
  (in particular, support as_numeric(), is_expression(), and is_relational()) 

- Adding a method to update the data in a results object
  to use (a) labels from the model and (b) variable IDs from the
  model.

- Changed the LP writer to write the true name of the objective.

- Misc bug fixes in NL writer.

- Adding a hook to see if the initialization function for a set 
  has a 'dimen' attribute.

- Overhaul of Constraint generation code
  - collapsing _LessThanExpression and _LesThanOrEqualExpression to a
    single _InequalityExpression that can hold 2 or 3 arguments
  - centralizing relational expression generation in
    expr.generate_relational_expression()
  - standardizing tests in constraint.add() to be more robust to
    unexpected input - slight performance improvement in constraint.add()

- Rework of expressions to perform a lazy cloning of expression subexpressions.
  This resolves bugs that a variety of users have reported.

- Improved error detection of constraints with non-finite bounds.

- Adding regression test for Pyomo benders example using CPLEX

- Adding a future import for integer division in various places,
  to resolve issues with integer data...

- Various updates to the pyomo command line:
  - Added a -c/--catch-exceptions option, which generates an error
    when exceptions are generated. The -d/--debug option does the same thing,
    but it generates lots of output!

- Rework of the pyomo command line to create a concise output

- Many efficiency improvements:
  - Preprocessing
  - Expression generation
  - Using Python slots logic to store data more efficiently
  - Replaced the product set iterator with itertools iterator
  - Automatic disabling of garbage collection during model generation
  - Eliminated expression verify() logic
  - Various loop optimizations
  - Eliminated the some preprocessing steps

- Many improvements to diagnostic output and error handling.  This includes the
  use of Python's logging utility, and the addition of options to
  the pyomo command line to control logging output.

- Fix to variable reset() logic.  After calling reset(), variable values will
  be None unless an initialization value is provide.

- Added a higher performance variation of the p-median example.

- Deprecating the use of 'Model' as the base abstract Model class.

- Setup various call-back functions that can be executed by the
  pyomo command line

- Added options to manage memory profiling

- Introduced a parameter representation class that allows for a more 
  robust experience using Param() objects with non-Pyomo data. Two
  parameter representations are supported:
  - pyomo_dict This is the default, and it supports data in ParamValue objects.
  - sparse_dict Use a class that looks like a sparse dictionary.

- Extended API of NumericValue objects so expressions like "model.p > 1" 
  can be used in conditionals.

-------------------------------------------------------------------------------
 2.5
-------------------------------------------------------------------------------

- Some progress toward functional indexed Piecewise components.

- Adding example of Piecewise construct using breakpoint and slope rules,
  as opposed to explicit/direct lists.

- Adding omitted pprint() method for SOS constraints.

- Fixing diagnostic error message when attempting to solve quadratic
  programs with GLPK - code for generating message was not syntatically
  legal.

- Interim fixes to output of quadratic terms in LP writer - more to do,
  but at least the basic examples now work.

- Migrated OS-specific functionality into coopr.os.

- Supressing a validation test with NumericConstant. If the user specifies
  a value, we are (now) assuming it is actually a numeric value - otherwise,
  the domain check significantly inflates the run-time associated with
  expression tree creation. This needs to be revisited in the Coopr
  2.5 re-write.

- Added a simple knapsack example to illustrate the difference between
  a concrete and abstract model.

- Fixing bugs in has_discrete_variables() method of PyomoModel.

- Eliminating initial domain check when constructing numeric constants
  and the default domain (Reals) is specified.

-------------------------------------------------------------------------------
 2.4
-------------------------------------------------------------------------------

- Fixing bug in ord() method of sets.

- Extending semantics of Pyomo scripting to recognize plugins that can
  be used to customize the Pyomo script behavior (e.g.  print results,
  save model instances, etc.)

- Misc changes that attempt to be more careful in how files are opened
  and closed. MS Windows is particularly sensitive about removing files
  that are currently open.

- Rework of tests to use new plugin factory mechanism
  supported by pyutilib.component.core

- Some performance improvements in identify_vars.py, obtained by
  significantly reducing the number of times that the type query (e.g.,
  is_binary, isinstance) methods of variables are called.

- Introduced the ConcreteModel and AbstractModel classes, to clearly denote
  the type of model that the Pyomo user is defining.

- Adding debug output to report when each variable is constructed, as with
  parameters, sets, constraints, and objectives. 

- Allow the same value is added to a set twice. This
  shouldn't cause an error.

- Added a "noruleinit" keyword option to the Constraint and Objective
  classes.  If specified, then the following hold: (1) the user is
  explicitly taking responsibility for constructing individual index
  elements for instances of these classes.  (2) no warning will be output
  if no "rule" or "expr" keywords are specified in the constructors of
  these classes.  This change was motivated by the silence of pyomo if
  no rule is specified in a constraint constructor, making model error
  diagnostics more difficult than they need be. If no rule is specified
  and the noruleinit keyword is absent, then Pyomo will output a warning
  message indicating the situation.

- Adding a warning in cases where users specify both the rule and
  noinitrule keywords in the Constraint and Objective class
  constructors. If a rule is specified, it will be used.

- Added more useful error messages for a variety of contexts of modeling errors.

- Changed error checking logic for all derived classes of Component.
  Before, IndexedComponent would perform error checking to ensure that
  a ctype was being passed to the Component constructor. Now that error
  checking occurs in Component; this is to allow classes to derive from
  Component without also deriving from IndexedComponent.

- Added new abstract base class ConstraintBase.  ConstraintBase will
  serve as a base class for all constraint-like objects.  Currently only
  Constraint exists; however, this change is in preparation for SOS1,
  SOS2, and SOS-n constraint classes, among others.

- Changes to coopr.pyomo to support SOS constraints.

- Changed default behavior of SOSConstraint.  SOSConstraint used to
  assign a default value of '1' to the 'sos' or 'level' keywords if none
  were provided by the user. It now raises a TypeError asking the user to
  specify the value.

- Adds Piecewise variables.  Piecewise objects are variables that are
  constrained to have a value determined by a piecewise linear
  function. If the piecewise linear function is concave or convex, the
  variable is constrained by a number of lienar constraints. If it is
  nonconvex, then it is comstrained using SOS2 sets.

- Updates to the pyomo command line:
  - Added '-i' option to drop the user to an interactive shell when
    an error occurs.
  - Alphabetized options and split into logical groups.

- Reformated output of LP files to support a maximum line-length (510
  characters).

- Added support for generalized sums over k sets (like in AMPL)
  The multisum function can be used to support a summation such as:
    sum(model.A[i,j,k] for (i,j,k) in multisum(setI, setJ, setK))

- Updates to allow indexed variables to contain both
  continuous and discrete variables. This is accomplished by allowing
  the 'within' and 'domain' keywords to accept a rule that return the
  set each variable should be a part of. These changes should be mostly
  transparent to the user unless they seek out this functionality.

- Adding EqualityTransform, which creates an equivalent form of a model
  by replacing inequality constraints with equality constraints and
  slack and excess variables.

- Added a class heirarchy for model transformations: non/linear,
  abstract/concrete, non/isomorphic.  Note that each group encompasses
  all possible transformations; specifically, every transformation is
  either linear or not linear, abstract or not abstract, and isomorphic
  or not isomorphic. Derived transformations are designed to multiply
  inherit. Failing to inherit from one group shows indifference to
  that group.

- Adding a Block component, which is a base class for Model.  Note that
  this is a preliminary implementation. I haven't added added logic
  for recursing through subblocks.  To retain backwards compatibility,
  we don't need that functionality.

- Added nonlinear support to pyomo. This includes new intrinsic functions and
  new NL writer as well as corresponding tests.

- Changed semantics of Python operators.  Now, new expressions are returned 
  when an operator is applied, rather than editing one of the operators in
  place.

- Resolved various Pyomo data file parse errors

- Added support for ODBC data imports.  This includes support using the pyodbc
  python package (if it's installed).  

- Allow Pyomo components to automatically find rules with corresponding names:

  def c_rule(model):
    return model.x
  model.c = Constraint()

- Adding support for non-mutable parameters, which are now
  the default. These are simply parameters that are stored as
  dictionaries with float values rather than ParamValue? values.

- Adding logic to allow ASL solverss to be specified as:

    --solver=asl:PICO

- Rework to set the sys.path environment to find the PLY parser tables. 
  This should allow the parse table to be written only once.

- Various performance-related enhancements that rework the internals of
  numeric values and constants.

- Adding logic for LP writer when dealing with linearized expressions
  involving fixed variables. 

- Added "has_discrete_variables" method to PyomoModel?, to support query
  by MIP plugins - which often need this method to determine the type
  of solution information (e.g., duals) to extract.

- Added a "nochecking" keyword argument to Params. Intended strictly
  for use by algorithm developers, it by-passes the call to
  _valid_indexed_component, which was taking a huge amount of time in
  various PySP algorithms. Use sparingly and judiciously! May also apply
  in the near future to other aspects of setitem.

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

