source: trunk/coopr/pysp/ef.py @ 1753

Last change on this file since 1753 was 1753, checked in by jwatson, 11 years ago

Added model and instance directory options to the ef writer.

File size: 35.8 KB
Line 
1import sys
2import os
3import time
4import traceback
5import copy
6
7from coopr.pysp.scenariotree import *
8from coopr.pysp.convergence import *
9from coopr.pysp.ph import *
10
11from coopr.pyomo.base import *
12from coopr.pyomo.io import *
13
14from coopr.pyomo.base.var import _VarValue, _VarBase
15
16# brain-dead utility for determing if there is a binary to write in the
17# composite model - need to know this, because CPLEX doesn't like empty
18# binary blocks in the LP file.
19def binaries_present(master_model, scenario_instances):
20
21   # check the master model first.
22   for var in master_model._component[_VarBase].values():
23      if isinstance(var.domain, BooleanSet):
24         return True
25
26   # scan the scenario instances next.
27   for scenario_name in scenario_instances.keys():
28      scenario_instance = scenario_instances[scenario_name]
29      for var in scenario_instance._component[_VarBase].values():
30         if isinstance(var.domain, BooleanSet):
31            return True
32
33   return False
34
35# brain-dead utility for determing if there is a binary to write in the
36# composite model - need to know this, because CPLEX doesn't like empty
37# integer blocks in the LP file.
38def integers_present(master_model, scenario_instances):
39
40   # check the master model first.
41   for var in master_model._component[_VarBase].values():
42      if isinstance(var.domain, IntegerSet):
43         return True
44
45   # scan the scenario instances next.
46   for scenario_name in scenario_instances.keys():
47      scenario_instance = scenario_instances[scenario_name]
48      for var in scenario_instance._component[_VarBase].values():
49         if isinstance(var.domain, IntegerSet):
50            return True
51
52   return False
53
54# the main extensive-form writer routine - including read of scenarios/etc.
55def write_ef_from_scratch(model_directory, instance_directory, output_filename):
56
57   start_time = time.time()
58
59   scenario_data_directory_name = instance_directory
60
61   print "Initializing extensive form writer"
62   print ""
63
64   ################################################################################################
65   #### INITIALIZATION ############################################################################
66   ################################################################################################
67   
68   #
69   # create and populate the core model
70   #
71   reference_model_filename = model_directory+os.sep+"ReferenceModel.py"   
72   modelimport = pyutilib.import_file(reference_model_filename)
73   filter_excepthook=False
74   if "model" not in dir(modelimport):
75      print ""
76      print "Exiting test driver: No 'model' object created in module "+reference_model_filename
77      sys.exit(0)
78   if modelimport.model is None:
79      print ""
80      print "Exiting test driver: 'model' object equals 'None' in module "+reference_model_filename
81      sys.exit(0)
82
83   master_scenario_model = modelimport.model
84
85   reference_scenario_filename = instance_directory+os.sep+"ReferenceModel.dat"
86   master_scenario_instance = master_scenario_model.create(reference_scenario_filename)
87
88   #
89   # create and populate the scenario tree model
90   #
91
92   treeimport = pyutilib.import_file(model_directory+os.sep+"ScenarioStructure.py")
93
94   tree_data = treeimport.model.create(instance_directory+os.sep+"ScenarioStructure.dat")
95
96   #
97   # construct the scenario tree
98   #
99   scenario_tree = ScenarioTree(model=master_scenario_instance,
100                                nodes=tree_data.Nodes,
101                                nodechildren=tree_data.Children,
102                                nodestages=tree_data.NodeStage,
103                                nodeprobabilities=tree_data.ConditionalProbability,
104                                stages=tree_data.Stages,
105                                stagevariables=tree_data.StageVariables,
106                                stagecostvariables=tree_data.StageCostVariable,
107                                scenarios=tree_data.Scenarios,
108                                scenarioleafs=tree_data.ScenarioLeafNode,
109                                scenariobaseddata=tree_data.ScenarioBasedData)
110
111   #
112   # print the input tree for validation/information purposes.
113   #
114   scenario_tree.pprint()
115
116   #
117   # validate the tree prior to doing anything serious
118   #
119   print ""
120   if scenario_tree.validate() is False:
121      print "***Scenario tree is invalid****"
122      sys.exit(1)
123   else:
124      print "Scenario tree is valid!"
125   print ""
126
127   #
128   # construct instances for each scenario
129   #
130
131   instances = {}
132   
133   if scenario_tree._scenario_based_data == 1:
134      print "Scenario-based instance initialization enabled"
135   else:
136      print "Node-based instance initialization enabled"
137         
138   for scenario in scenario_tree._scenarios:
139
140      scenario_instance = None
141
142      print "Creating instance for scenario=" + scenario._name
143
144      try:
145         if scenario_tree._scenario_based_data == 1:
146            scenario_data_filename = scenario_data_directory_name + os.sep + scenario._name + ".dat"
147#            print "Data for scenario=" + scenario._name + " loads from file=" + scenario_data_filename
148            scenario_instance = master_scenario_model.create(scenario_data_filename)
149         else:
150            scenario_instance = master_scenario_model.clone()
151            scenario_data = ModelData()
152            current_node = scenario._leaf_node
153            while current_node is not None:
154               node_data_filename = scenario_data_directory_name + os.sep + current_node._name + ".dat"
155#               print "Node data for scenario=" + scenario._name + " partially loading from file=" + node_data_filename
156               scenario_data.add_data_file(node_data_filename)
157               current_node = current_node._parent
158            scenario_data.read(model=scenario_instance)
159            scenario_instance._load_model_data(scenario_data)
160            scenario_instance.presolve()
161      except:
162         print "Encountered exception in model instance creation - traceback:"
163         traceback.print_exc()
164         raise RuntimeError, "Failed to create model instance for scenario=" + scenario._name
165
166      # name each instance with the scenario name, so the prefixes in the EF make sense.
167      scenario_instance.name = scenario._name
168     
169      scenario_instance.presolve()
170      instances[scenario._name] = scenario_instance
171
172   print ""
173
174   ################################################################################################
175   #### CREATE THE MASTER / BINDING INSTANCE ######################################################
176   ################################################################################################
177
178   master_binding_instance = Model()
179   master_binding_instance.name = "MASTER"
180
181   # walk the scenario tree - create variables representing the common values for all scenarios
182   # associated with that node. the constraints will be created later. also create expected-cost
183   # variables for each node, to be computed via constraints/objectives defined in a subsequent pass.
184   # master variables are created for all nodes but those in the last stage. expected cost variables
185   # are, for no particularly good reason other than easy coding, created for nodes in all stages.
186   print "Creating variables for master binding instance"
187
188   for stage in scenario_tree._stages:
189
190      for (stage_variable, index_template, stage_variable_indices) in stage._variables:
191
192         print "Creating master variable and blending constraints for decision variable=", stage_variable, ", indices=", stage_variable_indices
193
194         for tree_node in stage._tree_nodes:
195
196            if stage != scenario_tree._stages[-1]:     
197
198               master_variable_name = tree_node._name + "_" + stage_variable.name
199
200               # because there may be a single stage variable and multiple indices, check
201               # for the existence of the variable at this node - if you don't, you'll
202               # inadvertently over-write what was there previously!
203               master_variable = None
204               try:
205                  master_variable = getattr(master_binding_instance, master_variable_name)
206               except:
207                  # the deepcopy is probably too expensive (and unnecessary) computationally -
208                  # easier to just use the constructor with the stage variable index/bounds/etc.
209                  # NOTE: need to re-assign the master variables for each _varval - they probably
210                  #       point to a bogus model.
211                  new_master_variable = copy.deepcopy(stage_variable)
212                  new_master_variable.name = master_variable_name
213                  new_master_variable._model = master_binding_instance
214                  setattr(master_binding_instance, master_variable_name, new_master_variable)
215
216                  master_variable = new_master_variable
217
218               for index in stage_variable_indices:
219
220                  is_used = True # until proven otherwise                     
221                  for scenario in tree_node._scenarios:
222                     instance = instances[scenario._name]
223                     if getattr(instance,stage_variable.name)[index].status == VarStatus.unused:
224                        is_used = False
225
226                  is_fixed = False # until proven otherwise
227                  for scenario in tree_node._scenarios:
228                     instance = instances[scenario._name]
229                     if getattr(instance,stage_variable.name)[index].fixed is True:
230                        is_fixed = True
231
232                  if (is_used is True) and (is_fixed is False):
233                           
234                     # the following is necessary, specifically to get the name - deepcopy won't reset these attributes.
235                     # and because presolve/simplification is name-based, the names *have* to be different.
236                     master_variable[index].var = master_variable
237                     master_variable[index].name = tree_node._name + "_" + master_variable[index].name
238
239                     for scenario in tree_node._scenarios:
240
241                        scenario_instance = instances[scenario._name]
242                        scenario_variable = getattr(scenario_instance, stage_variable.name)
243                        new_constraint_name = scenario._name + "_" + master_variable_name + "_" + str(index)
244                        new_constraint = Constraint(name=new_constraint_name)
245                        new_expr = master_variable[index] - scenario_variable[index]
246                        new_constraint._initialize_constraint(None, (0.0, new_expr, 0.0), master_binding_instance, new_constraint_name)
247                        new_constraint._model = master_binding_instance
248                        setattr(master_binding_instance, new_constraint_name, new_constraint)
249
250            # create a variable to represent the expected cost at this node -
251            # the constraint to compute this comes later.
252            expected_cost_variable_name = "EXPECTED_COST_" + tree_node._name
253            expected_cost_variable = Var(name=expected_cost_variable_name)
254            expected_cost_variable._model = master_binding_instance
255            setattr(master_binding_instance, expected_cost_variable_name, expected_cost_variable)
256
257   master_binding_instance.presolve()
258
259   # ditto above for the (non-expected) cost variable.
260   for stage in scenario_tree._stages:
261
262      (cost_variable,cost_variable_index) = stage._cost_variable
263
264      print "Creating master variable and blending constraints for cost variable=", cost_variable, ", index=", cost_variable_index     
265
266      for tree_node in stage._tree_nodes:
267
268         new_cost_variable_name = tree_node._name + "_" + cost_variable.name
269
270         # TBD - the following is bad - check to see if it's already there (I suspect some of them are!!!)
271
272         # this is undoubtedly wasteful, in that a cost variable
273         # for each tree node is created with *all* indices.
274         new_cost_variable = copy.deepcopy(cost_variable)
275         new_cost_variable.name = new_cost_variable_name
276         new_cost_variable._model = master_binding_instance
277         setattr(master_binding_instance, new_cost_variable_name, new_cost_variable)
278
279         # the following is necessary, specifically to get the name - deepcopy won't reset these attributes.
280         new_cost_variable[cost_variable_index].var = new_cost_variable
281         if cost_variable_index is not None:
282            # if the variable index is None, the variable is derived from a VarValue, so the
283            # name gets updated automagically.
284            new_cost_variable[cost_variable_index].name = tree_node._name + "_" + new_cost_variable[cost_variable_index].name
285
286         for scenario in tree_node._scenarios:
287
288            scenario_instance = instances[scenario._name]
289            scenario_cost_variable = getattr(scenario_instance, cost_variable.name)
290            new_constraint_name = scenario._name + "_" + new_cost_variable_name + "_" + str(cost_variable_index)
291            new_constraint = Constraint(name=new_constraint_name)
292            new_expr = new_cost_variable[cost_variable_index] - scenario_cost_variable[cost_variable_index]
293            new_constraint._initialize_constraint(None, (0.0, new_expr, 0.0), master_binding_instance, new_constraint_name)
294            new_constraint._model = master_binding_instance
295            setattr(master_binding_instance, new_constraint_name, new_constraint)
296
297   # create the constraints for computing the master per-node cost variables,
298   # i.e., the current node cost and the expected cost of the child nodes.
299   # if the root, then the constraint is just the objective.
300
301   for stage in scenario_tree._stages:
302
303      (stage_cost_variable,stage_cost_variable_index) = stage._cost_variable
304
305      for tree_node in stage._tree_nodes:
306
307         node_expected_cost_variable_name = "EXPECTED_COST_" + tree_node._name
308         node_expected_cost_variable = getattr(master_binding_instance, node_expected_cost_variable_name)
309
310         node_cost_variable_name = tree_node._name + "_" + stage_cost_variable.name
311         node_cost_variable = getattr(master_binding_instance, node_cost_variable_name)                       
312           
313         constraint_expr = node_expected_cost_variable - node_cost_variable[stage_cost_variable_index]
314
315         for child_node in tree_node._children:
316
317            child_node_expected_cost_variable_name = "EXPECTED_COST_" + child_node._name
318            child_node_expected_cost_variable = getattr(master_binding_instance, child_node_expected_cost_variable_name)
319            constraint_expr = constraint_expr - (child_node._conditional_probability * child_node_expected_cost_variable)
320
321         new_constraint_name = "COST" + "_" + node_cost_variable_name + "_" + str(cost_variable_index)
322         new_constraint = Constraint(name=new_constraint_name)
323         new_constraint._initialize_constraint(None, (0.0, constraint_expr, 0.0), master_binding_instance, new_constraint_name)
324         new_constraint._model = master_binding_instance                     
325         setattr(master_binding_instance, new_constraint_name, new_constraint)
326
327         if tree_node._parent is None:
328
329            an_instance = instances[instances.keys()[0]]
330            an_objective = an_instance._component[Objective]
331            opt_sense = an_objective[an_objective.keys()[0]].sense
332
333            new_objective = Objective(name="MASTER", sense=opt_sense)
334            new_objective._data[None].expr = node_expected_cost_variable
335            setattr(master_binding_instance, "MASTER", new_objective)
336
337   master_binding_instance.presolve()
338
339   ################################################################################################
340   #### WRITE THE COMPOSITE MODEL #################################################################
341   ################################################################################################
342
343   print ""
344   print "Starting to write extensive form"
345
346   # create the output file.
347   problem_writer = cpxlp.ProblemWriter_cpxlp()
348   output_file = open(output_filename,"w")
349
350   problem_writer._output_prefixes = True # we always want prefixes
351
352   ################################################################################################
353   #### WRITE THE MASTER OBJECTIVE ################################################################
354   ################################################################################################
355
356   # write the objective for the master binding instance.
357   problem_writer._output_objectives = True
358   problem_writer._output_constraints = False
359   problem_writer._output_variables = False
360
361   print >>output_file, "\\ Begin objective block for master"
362   problem_writer._print_model_LP(master_binding_instance, output_file)
363   print >>output_file, "\\ End objective block for master"
364   print >>output_file, ""
365
366   ################################################################################################
367   #### WRITE THE CONSTRAINTS FOR THE MASTER MODEL AND ALL SCENARIO MODELS ########################
368   ################################################################################################
369
370   print >>output_file, "s.t."
371   print >>output_file, ""
372   
373   problem_writer._output_objectives = False
374   problem_writer._output_constraints = True
375   problem_writer._output_variables = False
376
377   print >>output_file, "\\ Begin constraint block for master"
378   problem_writer._print_model_LP(master_binding_instance, output_file)
379   print >>output_file, "\\ End constraint block for master",
380   print >>output_file, ""
381
382   for scenario_name in instances.keys():
383      instance = instances[scenario_name]
384      print >>output_file, "\\ Begin constraint block for scenario",scenario_name       
385      problem_writer._print_model_LP(instance, output_file)
386      print >>output_file, "\\ End constraint block for scenario",scenario_name
387      print >>output_file, ""
388
389   ################################################################################################
390   #### WRITE THE VARIABLES FOR THE MASTER MODEL AND ALL SCENARIO MODELS ##########################
391   ################################################################################################
392
393   # write the variables for the master binding instance, and then for each scenario.
394   print >>output_file, "bounds"
395   print >>output_file, ""
396   
397   problem_writer._output_objectives = False
398   problem_writer._output_constraints = False
399   problem_writer._output_variables = True
400
401   # first step: write variable bounds
402
403   problem_writer._output_continuous_variables = True
404   problem_writer._output_integer_variables = False
405   problem_writer._output_binary_variables = False
406
407   print >>output_file, "\\ Begin variable bounds block for master"
408   problem_writer._print_model_LP(master_binding_instance, output_file)
409   print >>output_file, "\\ End variable bounds block for master"
410   print >>output_file, ""
411
412   for scenario_name in instances.keys():
413      instance = instances[scenario_name]
414      print >>output_file, "\\ Begin variable bounds block for scenario",scenario_name
415      problem_writer._print_model_LP(instance, output_file)
416      print >>output_file, "\\ End variable bounds block for scenario",scenario_name
417      print >>output_file, ""
418
419   # second step: write integer indicators.
420
421   problem_writer._output_continuous_variables = False
422   problem_writer._output_integer_variables = True
423
424   if integers_present(master_binding_instance, instances) is True:
425
426      print >>output_file, "integer"
427      print >>output_file, ""
428
429      print >>output_file, "\\ Begin integer variable block for master"
430      problem_writer._print_model_LP(master_binding_instance, output_file)
431      print >>output_file, "\\ End integer variable block for master"
432      print >>output_file, ""
433   
434      for scenario_name in instances.keys():
435         instance = instances[scenario_name]
436         print >>output_file, "\\ Begin integer variable block for scenario",scenario_name
437         problem_writer._print_model_LP(instance, output_file)
438         print >>output_file, "\\ End integer variable block for scenario",scenario_name
439         print >>output_file, ""
440
441   # third step: write binary indicators.
442
443   problem_writer._output_integer_variables = False
444   problem_writer._output_binary_variables = True
445
446   if binaries_present(master_binding_instance, instances) is True:
447
448      print >>output_file, "binary"
449      print >>output_file, ""
450
451      print >>output_file, "\\ Begin binary variable block for master"
452      problem_writer._print_model_LP(master_binding_instance, output_file)
453      print >>output_file, "\\ End binary variable block for master"
454      print >>output_file, ""
455   
456      for scenario_name in instances.keys():
457         instance = instances[scenario_name]
458         print >>output_file, "\\ Begin binary variable block for scenario",scenario_name
459         problem_writer._print_model_LP(instance, output_file)
460         print >>output_file, "\\ End integer binary block for scenario",scenario_name
461         print >>output_file, ""
462
463   # wrap up.
464   print >>output_file, "end"
465
466   # clean up.
467   output_file.close()
468
469   print ""
470   print "Output file written to file=",output_filename
471
472   print ""
473   print "Done..."
474
475   end_time = time.time()
476
477   print ""
478   print "Total execution time=%8.2f seconds" %(end_time - start_time)
479   print ""
480
481def write_ef(scenario_tree, instances, output_filename):
482
483   start_time = time.time()
484
485   ################################################################################################
486   #### CREATE THE MASTER / BINDING INSTANCE ######################################################
487   ################################################################################################
488
489   master_binding_instance = Model()
490   master_binding_instance.name = "MASTER"
491
492   # walk the scenario tree - create variables representing the common values for all scenarios
493   # associated with that node. the constraints will be created later. also create expected-cost
494   # variables for each node, to be computed via constraints/objectives defined in a subsequent pass.
495   # master variables are created for all nodes but those in the last stage. expected cost variables
496   # are, for no particularly good reason other than easy coding, created for nodes in all stages.
497   print "Creating variables for master binding instance"
498
499   for stage in scenario_tree._stages:
500
501      for (stage_variable, index_template, stage_variable_indices) in stage._variables:
502
503         print "Creating master variable and blending constraints for decision variable=", stage_variable, ", indices=", index_template
504
505         for tree_node in stage._tree_nodes:
506
507            if stage != scenario_tree._stages[-1]:     
508
509               master_variable_name = tree_node._name + "_" + stage_variable.name
510
511               # because there may be a single stage variable and multiple indices, check
512               # for the existence of the variable at this node - if you don't, you'll
513               # inadvertently over-write what was there previously!
514               master_variable = None
515               try:
516                  master_variable = getattr(master_binding_instance, master_variable_name)
517               except:
518                  # the deepcopy is probably too expensive (and unnecessary) computationally -
519                  # easier to just use the constructor with the stage variable index/bounds/etc.
520                  # NOTE: need to re-assign the master variables for each _varval - they probably
521                  #       point to a bogus model.
522                  new_master_variable = copy.deepcopy(stage_variable)
523                  new_master_variable.name = master_variable_name
524                  new_master_variable._model = master_binding_instance
525                  setattr(master_binding_instance, master_variable_name, new_master_variable)
526
527                  master_variable = new_master_variable
528
529               for index in stage_variable_indices:
530
531                  is_used = True # until proven otherwise                     
532                  for scenario in tree_node._scenarios:
533                     instance = instances[scenario._name]
534                     if getattr(instance,stage_variable.name)[index].status == VarStatus.unused:
535                        is_used = False
536
537                  is_fixed = False # until proven otherwise
538                  for scenario in tree_node._scenarios:
539                     instance = instances[scenario._name]
540                     if getattr(instance,stage_variable.name)[index].fixed is True:
541                        is_fixed = True
542
543                  if (is_used is True) and (is_fixed is False):
544                           
545                     # the following is necessary, specifically to get the name - deepcopy won't reset these attributes.
546                     # and because presolve/simplification is name-based, the names *have* to be different.
547                     master_variable[index].var = master_variable
548                     master_variable[index].name = tree_node._name + "_" + master_variable[index].name
549
550                     for scenario in tree_node._scenarios:
551
552                        scenario_instance = instances[scenario._name]
553                        scenario_variable = getattr(scenario_instance, stage_variable.name)
554                        new_constraint_name = scenario._name + "_" + master_variable_name + "_" + str(index)
555                        new_constraint = Constraint(name=new_constraint_name)
556                        new_expr = master_variable[index] - scenario_variable[index]
557                        new_constraint._initialize_constraint(None, (0.0, new_expr, 0.0), master_binding_instance, new_constraint_name)
558                        new_constraint._model = master_binding_instance
559                        setattr(master_binding_instance, new_constraint_name, new_constraint)
560
561            # create a variable to represent the expected cost at this node -
562            # the constraint to compute this comes later.
563            expected_cost_variable_name = "EXPECTED_COST_" + tree_node._name
564            expected_cost_variable = Var(name=expected_cost_variable_name)
565            expected_cost_variable._model = master_binding_instance
566            setattr(master_binding_instance, expected_cost_variable_name, expected_cost_variable)
567
568   master_binding_instance.presolve()
569
570   # ditto above for the (non-expected) cost variable.
571   for stage in scenario_tree._stages:
572
573      (cost_variable,cost_variable_index) = stage._cost_variable
574
575      print "Creating master variable and blending constraints for cost variable=", cost_variable, ", index=", cost_variable_index     
576
577      for tree_node in stage._tree_nodes:
578
579         new_cost_variable_name = tree_node._name + "_" + cost_variable.name
580
581         # TBD - the following is bad - check to see if it's already there (I suspect some of them are!!!)
582
583         # this is undoubtedly wasteful, in that a cost variable
584         # for each tree node is created with *all* indices.
585         new_cost_variable = copy.deepcopy(cost_variable)
586         new_cost_variable.name = new_cost_variable_name
587         new_cost_variable._model = master_binding_instance
588         setattr(master_binding_instance, new_cost_variable_name, new_cost_variable)
589
590         # the following is necessary, specifically to get the name - deepcopy won't reset these attributes.
591         new_cost_variable[cost_variable_index].var = new_cost_variable
592         if cost_variable_index is not None:
593            # if the variable index is None, the variable is derived from a VarValue, so the
594            # name gets updated automagically.
595            new_cost_variable[cost_variable_index].name = tree_node._name + "_" + new_cost_variable[cost_variable_index].name
596
597         for scenario in tree_node._scenarios:
598
599            scenario_instance = instances[scenario._name]
600            scenario_cost_variable = getattr(scenario_instance, cost_variable.name)
601            new_constraint_name = scenario._name + "_" + new_cost_variable_name + "_" + str(cost_variable_index)
602            new_constraint = Constraint(name=new_constraint_name)
603            new_expr = new_cost_variable[cost_variable_index] - scenario_cost_variable[cost_variable_index]
604            new_constraint._initialize_constraint(None, (0.0, new_expr, 0.0), master_binding_instance, new_constraint_name)
605            new_constraint._model = master_binding_instance
606            setattr(master_binding_instance, new_constraint_name, new_constraint)
607
608   # create the constraints for computing the master per-node cost variables,
609   # i.e., the current node cost and the expected cost of the child nodes.
610   # if the root, then the constraint is just the objective.
611
612   for stage in scenario_tree._stages:
613
614      (stage_cost_variable,stage_cost_variable_index) = stage._cost_variable
615
616      for tree_node in stage._tree_nodes:
617
618         node_expected_cost_variable_name = "EXPECTED_COST_" + tree_node._name
619         node_expected_cost_variable = getattr(master_binding_instance, node_expected_cost_variable_name)
620
621         node_cost_variable_name = tree_node._name + "_" + stage_cost_variable.name
622         node_cost_variable = getattr(master_binding_instance, node_cost_variable_name)                       
623           
624         constraint_expr = node_expected_cost_variable - node_cost_variable[stage_cost_variable_index]
625
626         for child_node in tree_node._children:
627
628            child_node_expected_cost_variable_name = "EXPECTED_COST_" + child_node._name
629            child_node_expected_cost_variable = getattr(master_binding_instance, child_node_expected_cost_variable_name)
630            constraint_expr = constraint_expr - (child_node._conditional_probability * child_node_expected_cost_variable)
631
632         new_constraint_name = "COST" + "_" + node_cost_variable_name + "_" + str(cost_variable_index)
633         new_constraint = Constraint(name=new_constraint_name)
634         new_constraint._initialize_constraint(None, (0.0, constraint_expr, 0.0), master_binding_instance, new_constraint_name)
635         new_constraint._model = master_binding_instance                     
636         setattr(master_binding_instance, new_constraint_name, new_constraint)
637
638         if tree_node._parent is None:
639
640            an_instance = instances[instances.keys()[0]]
641            an_objective = an_instance._component[Objective]
642            opt_sense = an_objective[an_objective.keys()[0]].sense
643
644            new_objective = Objective(name="MASTER", sense=opt_sense)
645            new_objective._data[None].expr = node_expected_cost_variable
646            setattr(master_binding_instance, "MASTER", new_objective)
647
648   master_binding_instance.presolve()
649
650   ################################################################################################
651   #### WRITE THE COMPOSITE MODEL #################################################################
652   ################################################################################################
653
654   print ""
655   print "Starting to write extensive form"
656
657   # create the output file.
658   problem_writer = cpxlp.ProblemWriter_cpxlp()
659   output_file = open(output_filename,"w")
660
661   problem_writer._output_prefixes = True # we always want prefixes
662
663   ################################################################################################
664   #### WRITE THE MASTER OBJECTIVE ################################################################
665   ################################################################################################
666
667   # write the objective for the master binding instance.
668   problem_writer._output_objectives = True
669   problem_writer._output_constraints = False
670   problem_writer._output_variables = False
671
672   print >>output_file, "\\ Begin objective block for master"
673   problem_writer._print_model_LP(master_binding_instance, output_file)
674   print >>output_file, "\\ End objective block for master"
675   print >>output_file, ""
676
677   ################################################################################################
678   #### WRITE THE CONSTRAINTS FOR THE MASTER MODEL AND ALL SCENARIO MODELS ########################
679   ################################################################################################
680
681   print >>output_file, "s.t."
682   print >>output_file, ""
683   
684   problem_writer._output_objectives = False
685   problem_writer._output_constraints = True
686   problem_writer._output_variables = False
687
688   print >>output_file, "\\ Begin constraint block for master"
689   problem_writer._print_model_LP(master_binding_instance, output_file)
690   print >>output_file, "\\ End constraint block for master",
691   print >>output_file, ""
692
693   for scenario_name in instances.keys():
694      instance = instances[scenario_name]
695      print >>output_file, "\\ Begin constraint block for scenario",scenario_name       
696      problem_writer._print_model_LP(instance, output_file)
697      print >>output_file, "\\ End constraint block for scenario",scenario_name
698      print >>output_file, ""
699
700   ################################################################################################
701   #### WRITE THE VARIABLES FOR THE MASTER MODEL AND ALL SCENARIO MODELS ##########################
702   ################################################################################################
703
704   # write the variables for the master binding instance, and then for each scenario.
705   print >>output_file, "bounds"
706   print >>output_file, ""
707   
708   problem_writer._output_objectives = False
709   problem_writer._output_constraints = False
710   problem_writer._output_variables = True
711
712   # first step: write variable bounds
713
714   problem_writer._output_continuous_variables = True
715   problem_writer._output_integer_variables = False
716   problem_writer._output_binary_variables = False
717
718   print >>output_file, "\\ Begin variable bounds block for master"
719   problem_writer._print_model_LP(master_binding_instance, output_file)
720   print >>output_file, "\\ End variable bounds block for master"
721   print >>output_file, ""
722   
723   for scenario_name in instances.keys():
724      instance = instances[scenario_name]
725      print >>output_file, "\\ Begin variable bounds block for scenario",scenario_name
726      problem_writer._print_model_LP(instance, output_file)
727      print >>output_file, "\\ End variable bounds block for scenario",scenario_name
728      print >>output_file, ""
729
730   # second step: write integer indicators.
731
732   problem_writer._output_continuous_variables = False
733   problem_writer._output_integer_variables = True
734
735   if integers_present(master_binding_instance, instances) is True:
736
737      print >>output_file, "integer"
738      print >>output_file, ""
739
740      print >>output_file, "\\ Begin integer variable block for master"
741      problem_writer._print_model_LP(master_binding_instance, output_file)
742      print >>output_file, "\\ End integer variable block for master"
743      print >>output_file, ""
744   
745      for scenario_name in instances.keys():
746         instance = instances[scenario_name]
747         print >>output_file, "\\ Begin integer variable block for scenario",scenario_name
748         problem_writer._print_model_LP(instance, output_file)
749         print >>output_file, "\\ End integer variable block for scenario",scenario_name
750         print >>output_file, ""
751
752   # third step: write binary indicators.
753
754   problem_writer._output_integer_variables = False
755   problem_writer._output_binary_variables = True
756
757   if binaries_present(master_binding_instance, instances) is True:
758
759      print >>output_file, "binary"
760      print >>output_file, ""
761
762      print >>output_file, "\\ Begin binary variable block for master"
763      problem_writer._print_model_LP(master_binding_instance, output_file)
764      print >>output_file, "\\ End binary variable block for master"
765      print >>output_file, ""
766   
767      for scenario_name in instances.keys():
768         instance = instances[scenario_name]
769         print >>output_file, "\\ Begin binary variable block for scenario",scenario_name
770         problem_writer._print_model_LP(instance, output_file)
771         print >>output_file, "\\ End integer binary block for scenario",scenario_name
772         print >>output_file, ""
773
774   # wrap up.
775   print >>output_file, "end"
776
777   # clean up.
778   output_file.close()
779
780   print ""
781   print "Output file written to file=",output_filename
782
783   print ""
784   print "Done..."
785
786   end_time = time.time()
787
788   print ""
789   print "Total execution time=%8.2f seconds" %(end_time - start_time)
790   print ""   
Note: See TracBrowser for help on using the repository browser.