Source code for idaes.core.util.cut_gen

##############################################################################
# Institute for the Design of Advanced Energy Systems Process Systems
# Engineering Framework (IDAES PSE Framework) Copyright (c) 2018, by the
# software owners: The Regents of the University of California, through
# Lawrence Berkeley National Laboratory,  National Technology & Engineering
# Solutions of Sandia, LLC, Carnegie Mellon University, West Virginia
# University Research Corporation, et al. All rights reserved.
# 
# Please see the files COPYRIGHT.txt and LICENSE.txt for full copyright and
# license information, respectively. Both files are also available online
# at the URL "https://github.com/IDAES/idaes".
##############################################################################
"""
This module provides utility functions for cut generation.
"""
from __future__ import division
from .var import none_if_empty as ne
from pyomo.environ import Var, Param, Block, Constraint, Set
from pyomo.core.base.constraint import SimpleConstraint

__author__ = "Qi Chen <qichen@andrew.cmu.edu>"

[docs]def self_proj_var_rule(main_var, disagg_var, var_set, lbda): def var_rule(_, *sets): if main_var[ne(sets)].fixed: return Constraint.NoConstraint else: return main_var[ne(sets)] == sum( disagg_var[sets, vs] * lbda[vs] for vs in var_set) return var_rule
[docs]def count_vars(old_block): """Count the number of non-fixed variables to clone""" count = sum( 1 for o in old_block.component_data_objects(ctype=Var, active=True, descend_into=False) if not o.fixed) for old_sub_block in old_block.component_objects(ctype=Block, active=True, descend_into=False): if 'equip' not in old_sub_block.name: # do not include linear constraints block or ports continue # clone block count += count_vars(old_sub_block) return count
[docs]def clone_block(old_block, new_block, var_set, lbda): """This function acts similarly to the built-in Pyomo clone function, but excludes entries that are undesired for this platform.""" clone_block_vars(old_block, new_block, var_set, lbda) clone_block_params(old_block, new_block) clone_block_sets(old_block, new_block) clone_block_constraints(old_block, new_block, var_set) for old_sub_block in old_block.\ component_objects(ctype=Block, active=True, descend_into=False): if 'equip' not in old_sub_block.name: # do not include linear constraints block or ports continue # clone block new_sub_block = Block() setattr(new_block, old_sub_block.local_name, new_sub_block) clone_block(old_sub_block, new_sub_block, var_set, lbda)
[docs]def clone_block_vars(old_block, new_block, var_set, lbda): for old_var in old_block.\ component_objects(ctype=Var, active=True, descend_into=False): if all(old_var[i].fixed for i in old_var._index): # variable is completely fixed. Do not disaggregate; simply copy. if old_var.is_indexed(): new_var = Var(old_var._index) else: new_var = Var() setattr(new_block, old_var.local_name, new_var) for i in old_var._index: copy_var_data(new_var[i], old_var[i]) else: # create new disaggregated variables if old_var.is_indexed(): new_var = Var(old_var._index, var_set) setattr(new_block, old_var.local_name, new_var) for i, vs in old_var._index * var_set: copy_var_data(new_var[i, vs], old_var[i]) # create new aggregated variables new_agg_var = Var(old_var._index) setattr(new_block, '_' + old_var.local_name + '_clone', new_agg_var) for i in old_var._index: copy_var_data(new_agg_var[i], old_var[i]) # create new aggregate constraints setattr( new_block, '_' + old_var.local_name + '_clone_defn', Constraint(old_var._index, rule=self_proj_var_rule( new_agg_var, new_var, var_set, lbda))) else: # if old_var is a SimpleVar, do not use index i new_var = Var(var_set) setattr(new_block, old_var.local_name, new_var) for vs in var_set: copy_var_data(new_var[vs], old_var) # create new aggregated variable new_agg_var = Var() setattr(new_block, '_' + old_var.local_name + '_clone', new_agg_var) copy_var_data(new_agg_var, old_var) # create new aggregate constraints setattr( new_block, '_' + old_var.local_name + '_clone_defn', Constraint(rule=self_proj_var_rule( new_agg_var, new_var, var_set, lbda)))
[docs]def copy_var_data(new_var_data, old_var_data): new_var_data.domain = old_var_data.domain new_var_data.setlb(old_var_data.lb) new_var_data.setub(old_var_data.ub) new_var_data.value = old_var_data.value new_var_data.fixed = old_var_data.fixed
[docs]def clone_block_params(old_block, new_block): for old_param in old_block.component_objects(ctype=Param, active=True, descend_into=False): # clone param new_param = Param( old_param._index, initialize=old_param.extract_values()) setattr(new_block, old_param.local_name, new_param)
[docs]def clone_block_sets(old_block, new_block): for old_set in old_block.component_objects(ctype=Set, active=True, descend_into=False): if old_set.local_name.endswith('_index'): continue # clone param new_param = Set( old_set._index, initialize=old_set.data()) setattr(new_block, old_set.local_name, new_param)
[docs]def clone_block_constraints(old_block, new_block, var_set): for old_constr in old_block.\ component_objects(ctype=Constraint, active=True, descend_into=False): # clone constraint if isinstance(old_constr, SimpleConstraint): new_constr = Constraint(var_set, rule=old_constr.rule) else: # old constraint is indexed new_constr = Constraint( list(old_constr._index), var_set, rule=old_constr.rule) setattr(new_block, old_constr.local_name, new_constr)
[docs]def get_sum_sq_diff(old_block, new_block): sum_sq_diff = 0 for old_var in old_block.\ component_objects(ctype=Var, active=True, descend_into=False): new_var = getattr(new_block, '_' + old_var.local_name + '_clone', None) # new_var = getattr(new_block, old_var.local_name + '_clone', None) if new_var is not None: # print(old_var.local_name) sum_sq_diff += sum( (new_var[i] - old_var[i].value) ** 2 for i in new_var._index if new_var is not None and not new_var[i].fixed) # recurse through valid subblocks for new_sub_block in new_block.\ component_map(ctype=Block, active=True).itervalues(): old_sub_block = getattr(old_block, new_sub_block.local_name, None) if old_sub_block is not None: sum_sq_diff += get_sum_sq_diff(old_sub_block, new_sub_block) return sum_sq_diff