Changeset 3217


Ignore:
Timestamp:
Nov 5, 2010 1:29:42 PM (10 years ago)
Author:
jwatson
Message:

Various updates to support heteogeneous index sets in PH for different nodes in the scenario tree - more work / testing remains.

Location:
coopr.pysp/trunk/coopr/pysp
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • coopr.pysp/trunk/coopr/pysp/convergence.py

    r3073 r3217  
    117117         if stage != scenario_tree._stages[-1]:
    118118
    119             for (reference_variable, index_template, reference_variable_indices) in stage._variables:
     119            for (reference_variable, index_template) in stage._variables:
    120120               
    121121               reference_variable_name = reference_variable.name
    122122               
    123123               for tree_node in stage._tree_nodes:
     124
     125                  variable_indices = tree_node._variable_indices[reference_variable_name]
    124126
    125127                  node_variable_average = tree_node._averages[reference_variable_name]
    126128                 
    127                   for index in reference_variable_indices:
     129                  for index in variable_indices:
    128130                     
    129131                     is_used = True # until proven otherwise
     
    174176         if stage != scenario_tree._stages[-1]:
    175177
    176             for (reference_variable, index_template, reference_variable_indices) in stage._variables:
     178            for (reference_variable, index_template) in stage._variables:
    177179               
    178180               reference_variable_name = reference_variable.name
     
    181183
    182184                  node_variable_average = tree_node._averages[reference_variable_name]
     185
     186                  variable_indices = tree_node._variable_indices[reference_variable_name]                 
    183187                 
    184                   for index in reference_variable_indices:
     188                  for index in variable_indices:
    185189
    186190                     # should think about nixing the magic constant below (not sure how to best pararamterize it).
  • coopr.pysp/trunk/coopr/pysp/ef.py

    r3156 r3217  
    109109      cvar_eta_variable.construct()               
    110110
    111       first_stage.add_variable(cvar_eta_variable, "*", [None])
     111      first_stage.add_variable(cvar_eta_variable, "*")
    112112
    113113      cvar_excess_variable_name = "CVAR_EXCESS"
     
    115115      cvar_excess_variable.construct()
    116116
    117       second_stage.add_variable(cvar_excess_variable, "*", [None])
     117      second_stage.add_variable(cvar_excess_variable, "*")
    118118
    119119      # create the eta and excess variable on a per-scenario basis,
     
    166166
    167167      # first loop is to create master (blended) variables across all stages but the last.
    168       for (stage_variable, index_template, stage_variable_indices) in stage._variables:
     168      for (stage_reference_variable, index_template) in stage._variables:
    169169
    170170         if verbose_output is True:
    171             print "Creating master variable and blending constraints for decision variable="+stage_variable.name+", indices="+str(index_template)
     171            print "Creating master variable and blending constraints for decision variable="+stage_reference_variable.name+", indices="+str(index_template)
    172172
    173173         for tree_node in stage._tree_nodes:
     
    175175            if stage != scenario_tree._stages[-1]:     
    176176
    177                master_variable_name = stage_variable.name               
     177               stage_variable_name = stage_reference_variable.name
     178
     179               stage_variable_indices = tree_node._variable_indices[stage_variable_name]
    178180
    179181               # because there may be a single stage variable and multiple indices, check
     
    182184               master_variable = None
    183185               try:
    184                   master_variable = getattr(binding_instance, master_variable_name)
     186                  master_variable = getattr(binding_instance, stage_variable_name)
    185187               except:
    186                   new_master_variable_index = stage_variable._index
     188                  new_master_variable_index = getattr(scenario_instances[tree_node._scenarios[0]._name], stage_variable_name)._index
    187189                  new_master_variable = None
    188190                  if (len(new_master_variable_index) is 1) and (None in new_master_variable_index):
    189                      new_master_variable = Var(name=stage_variable.name)
     191                     new_master_variable = Var(name=stage_variable_name)
    190192                  else:
    191                      new_master_variable = Var(new_master_variable_index, name=stage_variable.name)
     193                     new_master_variable = Var(new_master_variable_index, name=stage_variable_name)
    192194                  new_master_variable.construct()
    193195                  new_master_variable._model = binding_instance
    194                   setattr(binding_instance, master_variable_name, new_master_variable)
     196                  setattr(binding_instance, stage_variable_name, new_master_variable)
    195197
    196198                  master_variable = new_master_variable
     
    202204                  for scenario in tree_node._scenarios:
    203205                     instance = scenario_instances[scenario._name]
    204                      if getattr(instance,stage_variable.name)[index].status == VarStatus.unused:
     206                     if getattr(instance,stage_variable_name)[index].status == VarStatus.unused:
    205207                        is_used = False
    206208
     
    208210                  for scenario in tree_node._scenarios:
    209211                     instance = scenario_instances[scenario._name]
    210                      if getattr(instance,stage_variable.name)[index].fixed is True:
     212                     if getattr(instance,stage_variable_name)[index].fixed is True:
    211213                        is_fixed = True
    212214
     
    215217                     for scenario in tree_node._scenarios:
    216218                        scenario_instance = scenario_instances[scenario._name]
    217                         scenario_variable = getattr(scenario_instance, stage_variable.name)
    218                         new_constraint_name = scenario._name + "_" + master_variable_name + "_" + str(index)
     219                        scenario_variable = getattr(scenario_instance, stage_variable_name)
     220                        new_constraint_name = scenario._name + "_" + stage_variable_name + "_" + str(index)
    219221                        new_constraint = Constraint(name=new_constraint_name)
    220222                        new_expr = master_variable[index] - scenario_variable[index]
     
    633635      gc.enable()
    634636
     637   # with the scenario instances now available, have the scenario tree compute the
     638   # variable match indices at each node.
     639   scenario_tree.defineVariableIndexSets(scenario_instances)     
     640
    635641   print "Creating extensive form binding instance"
    636642
  • coopr.pysp/trunk/coopr/pysp/ph.py

    r3168 r3217  
    154154         for tree_node in stage._tree_nodes:
    155155
    156             for (variable, index_template, variable_indices) in stage._variables:
     156            for (variable, index_template) in stage._variables:
     157
     158               variable_indices = tree_node._variable_indices[variable.name]
    157159
    158160               for index in variable_indices:
     
    190192         for tree_node in stage._tree_nodes:
    191193
    192             for (variable, index_template, variable_indices) in stage._variables:
     194            for (variable, index_template) in stage._variables:
     195
     196               variable_indices = tree_node._variable_indices[variable.name]
    193197
    194198               for index in variable_indices:
     
    282286         for stage in self._scenario_tree._stages[:-1]: # no blending over the final stage, so no weights to worry about.
    283287
    284             for (variable, index_template, variable_indices) in stage._variables:
     288            for (variable, index_template) in stage._variables:
    285289
    286290               variable_name = variable.name
     
    306310         for stage in self._scenario_tree._stages[:-1]: # no blending over the final stage, so no rhos to worry about.
    307311
    308             for (variable, index_template, variable_indices) in stage._variables:
     312            for (variable, index_template) in stage._variables:
    309313
    310314               variable_name = variable.name
     
    668672         self._instance_augmented_attributes[scenario._name] = []
    669673
    670 
    671674      # perform a single pass of garbage collection and re-enable automatic collection.
    672675      if re_enable_gc is True:
    673676         gc.collect()
    674677         gc.enable()
     678
     679      # with the scenario instances now available, have the scenario tree compute the
     680      # variable match indices at each node.
     681      self._scenario_tree.defineVariableIndexSets(self._instances)
    675682
    676683      # let plugins know if they care - this callback point allows
     
    712719
    713720         stage_variables = {}
    714          for (reference_variable, index_template, reference_index) in stage._variables:
     721         for (reference_variable, index_template) in stage._variables:
    715722            if reference_variable.name not in stage_variables.keys():
    716723               stage_variables[reference_variable.name] = reference_variable
     
    924931         for tree_node in stage._tree_nodes:
    925932
    926             for (variable, index_template, variable_indices) in stage._variables:
     933            for (variable, index_template) in stage._variables:
    927934
    928935               variable_name = variable.name
     936
     937               variable_indices = tree_node._variable_indices[variable_name]
    929938
    930939               avg_parameter_name = "PHAVG_"+variable_name
     
    9961005         for tree_node in stage._tree_nodes:
    9971006
    998             for (variable, index_template, variable_indices) in stage._variables:
     1007            for (variable, index_template) in stage._variables:
    9991008
    10001009               variable_name = variable.name
     
    10021011               weight_parameter_name = "PHWEIGHT_"+variable_name
    10031012               rho_parameter_name = "PHRHO_"+variable_name
     1013
     1014               variable_indices = tree_node._variable_indices[variable_name]
    10041015
    10051016               for index in variable_indices:
     
    14001411   # just the variable/stage.
    14011412   #
    1402    def should_print(self, stage, variable, variable_indices):
     1413   def should_print(self, stage, variable):
    14031414
    14041415      if self._output_continuous_variable_stats is False:
     
    14291440         num_outputs_this_stage = 0 # tracks the number of outputs on a per-index basis.
    14301441
    1431          for (variable, index_template, variable_indices) in stage._variables:
     1442         for (variable, index_template) in stage._variables:
    14321443
    14331444            variable_name = variable.name
    14341445
    1435             if self.should_print(stage, variable, variable_indices) is True:
     1446            if self.should_print(stage, variable) is True:
    14361447
    14371448               num_outputs_this_variable = 0 # track, so we don't output the variable names unless there is an entry to report.
    14381449
    1439                for index in variable_indices:
    1440 
    1441                   weight_parameter_name = "PHWEIGHT_"+variable_name
    1442 
    1443                   num_outputs_this_index = 0 # track, so we don't output the variable index more than once.
    1444 
    1445                   for tree_node in stage._tree_nodes:
     1450               for tree_node in stage._tree_nodes:
     1451
     1452                  variable_indices = tree_node._variable_indices[variable_name]               
     1453
     1454                  for index in variable_indices:
     1455
     1456                     weight_parameter_name = "PHWEIGHT_"+variable_name
     1457
     1458                     num_outputs_this_index = 0 # track, so we don't output the variable index more than once.
    14461459
    14471460                     # determine if the variable/index pair is used across the set of scenarios (technically,
  • coopr.pysp/trunk/coopr/pysp/phobjective.py

    r3139 r3217  
    255255               break
    256256
    257       for (reference_variable, index_template, variable_indices) in stage._variables:
     257      for (reference_variable, index_template) in stage._variables:
    258258
    259259         variable_name = reference_variable.name
     
    281281
    282282         instance_variable = instance.active_components(Var)[variable_name]
     283
     284         variable_indices = variable_tree_node._variable_indices[variable_name]
    283285
    284286         for index in variable_indices:
  • coopr.pysp/trunk/coopr/pysp/phutils.py

    r3201 r3217  
    271271   for stage in scenario_tree._stages[:-1]:
    272272
    273       for (reference_variable, index_template, reference_indices) in stage._variables:
     273      for (reference_variable, index_template) in stage._variables:
    274274
    275275         if reference_variable.name not in instance_variables.keys():
  • coopr.pysp/trunk/coopr/pysp/scenariotree.py

    r3106 r3217  
    2626   # variable/match-template/variable-index triple.
    2727   #
    28    def _update_solution_map(self, variable, match_template, variable_indices):
     28   def _update_solution_map(self, variable, match_template):
     29
     30      variable_indices = self._variable_indices[variable.name]
    2931
    3032      # don't bother copying bounds for variables, as the values stored
     
    6971      # this is something that we might revisit if space/performance
    7072      # is an issue (space is the most likely issue)
    71       for variable, match_template, variable_indices in self._stage._variables:
    72          self._update_solution_map(variable, match_template, variable_indices)
     73      for variable, match_template in self._stage._variables:
     74         self._update_solution_map(variable, match_template)
    7375
    7476      self._solution_map_initialized = True
     
    8587      self._conditional_probability = conditional_probability # conditional on parent
    8688      self._scenarios = [] # a collection of all Scenarios passing through this node in the tree
     89      self._variable_indices = {} # a map from a variable name to the indices blended at this node.
    8790
    8891      # general use statistics for the variables at each node.
     
    112115      if initialize_solution is True:
    113116         self._initialize_solution_map()
     117
     118   #
     119   # given a set of scenario instances, compute the set of indices being blended
     120   # for each variable at this node.
     121   #
     122
     123   def defineVariableIndexSets(self, scenario_instances):
     124
     125      # find a representative scenario instance belonging to this node. the
     126      # first scenario is as good as any.
     127      scenario_instance = scenario_instances[self._scenarios[0]._name]
     128
     129      for reference_variable, match_template in self._stage._variables:
     130
     131         # the stage variable simply references the variable object in the
     132         # reference scenario instance - we need to grab the variable in the
     133         # scenario instance, as the index set might be different.
     134         variable_name = reference_variable.name
     135
     136         instance_variable = getattr(scenario_instance, variable_name)
     137
     138         match_indices = extractVariableIndices(instance_variable, match_template)
     139
     140         self._variable_indices[variable_name] = match_indices
    114141
    115142   #
     
    195222      self._tree_nodes = []
    196223
    197       # a collection of triples consisting of (1) a reference to a Pyomo model Var object, (2) the original match
    198       # template string (for output purposes), and (3) a *list* of the corresponding indices. the variables are
    199       # references to those objects belonging to the Pyomo reference scenario instance associated with the parent
    200       # ScenarioTree of this Stage.
    201       # NOTE: if the variable index is none, it is assumed that the entire variable is blended.
     224      # a collection of pairs consisting of (1) a reference to a Pyomo model Var object (in the reference scenario instance) and
     225      # (2) the original match template string (for output purposes). the specific indices that match belong to the tree node.
    202226      self._variables = []
    203227
     
    209233   # add a new variable to the stage, which will include updating the solution maps for each associated ScenarioTreeNode.
    210234   #
    211    def add_variable(self, variable, match_template, indices):
    212 
    213       self._variables.append((variable, match_template, indices))
    214 
    215       for tree_node in self._tree_nodes:
    216          tree_node._update_solution_map(variable, match_template, indices)
     235   def add_variable(self, variable, match_template):
     236
     237      self._variables.append((variable, match_template))
     238
     239      for tree_node in self._tree_nodes:
     240         tree_node._update_solution_map(variable, match_template)
    217241
    218242class Scenario(object):
     
    263287               variable = self._reference_instance.active_components(Var)[variable_name]
    264288
    265                # extract all "real", i.e., fully specified, indices matching the index template.
    266                match_indices = extractVariableIndices(variable, index_template)
    267 
    268                # there is a possibility that no indices match the input template.
    269                # if so, let the user know about it.
    270                if len(match_indices) == 0:
    271                   raise RuntimeError, "No indices match template="+str(index_template)+" for variable="+variable_name+" ; encountered in scenario tree specification for model="+self._reference_instance.name
    272 
    273                stage._variables.append((variable, index_template, match_indices))
     289               stage._variables.append((variable, index_template))
    274290
    275291            else:
     
    293309               match_indices.append(None)
    294310
    295                stage._variables.append((variable, "", match_indices))
     311               stage._variables.append((variable, ""))
    296312
    297313      for stage_id in stage_cost_variable_ids.keys():
     
    506522
    507523   #
     524   # given a set of scenario instances, compute the set of variable indices being blended at each node.
     525   # this can't be done until the scenario instances are available, as different scenarios can have
     526   # different index sets.
     527   #
     528
     529   def defineVariableIndexSets(self, scenario_instances):
     530
     531      for tree_node in self._tree_nodes:
     532
     533         tree_node.defineVariableIndexSets(scenario_instances)
     534
     535   #
    508536   # is the indicated scenario in the tree?
    509537   #
     
    717745
    718746      for stage in self._stages:
    719          # stage_var is a VarValue - the rest are strings and list of indices, respectively.
    720          for (stage_var, match_template, match_indices) in stage._variables:
     747         for (stage_var, match_template) in stage._variables:
    721748            if (variable.name == stage_var.name) and (index in match_indices):
    722749               return stage
     
    819846            print "\t\t" + tree_node._name
    820847         print "\tVariables: "
    821          for (variable, index_template, indices) in stage._variables:
    822             if (len(indices) == 1) and (indices[0] == None):
    823                print "\t\t" + variable.name
    824             else:
    825                print "\t\t",variable.name,":",index_template
     848         for (variable, index_template) in stage._variables:
     849            print "\t\t",variable.name,":",index_template
    826850         print "\tCost Variable: "
    827851         if stage._cost_variable[1] is None:
     
    867891            print "\tParent=" + "None"
    868892         print "\tVariables: "
    869          for (variable, index_template, indices) in tree_node._stage._variables:
     893         for (variable, index_template) in tree_node._stage._variables:
     894            indices = tree_node._variable_indices[variable.name]
    870895            solution_variable = tree_node._solutions[variable.name]
    871896            if (len(indices) == 1) and (indices[0] == None):
Note: See TracChangeset for help on using the changeset viewer.