Ejemplo n.º 1
0
def run_conf(scenario_instance_factory, index_list, num_scenarios_for_solution,
             num_scenarios_per_sample, full_scenario_tree, xhat_ph, options):

    if options.MRP_directory_basename is None:
        AllInOne = True

    sense = xhat_ph._scenario_tree._scenarios[0]._objective_sense

    # in order to handle the case of scenarios that are not equally
    # likely, we will split the expectations for Gsupk
    # BUT we are going to assume that the groups themselves are
    # equally likely and just scale by n_g and n_g-1 for Gbar and VarG

    # really not always needed...
    # http://www.eecs.berkeley.edu/~mhoemmen/cs194/Tutorials/variance.pdf
    g_supk_of_xhat = []
    g_bar = 0
    sum_xstar_obj_given_xhat = 0
    n_g = options.n_g

    for k in range(1, n_g + 1):

        gk_ph = None
        try:

            if AllInOne:

                start_index = num_scenarios_for_solution + \
                              (k-1)*num_scenarios_per_sample
                stop_index = start_index + num_scenarios_per_sample

                print("")
                print("Computing statistics for sample k=" + str(k) + ".")
                if options.verbose:
                    print("Bundle start index=" + str(start_index) +
                          ", stop index=" + str(stop_index) + ".")

                # compute this xstar solution for the EF associated with
                # sample k.

                print("Loading scenario instances and initializing "
                      "scenario tree for xstar scenario bundle.")

                gk_ph = ph_for_bundle(start_index, stop_index,
                                      scenario_instance_factory,
                                      full_scenario_tree, index_list, options)

            else:

                options.instance_directory = \
                    options.MRP_directory_basename+str(k)

                gk_ph = PHFromScratch(options)

            print("Creating the xstar extensive form.")
            print("")
            print("Composite scenarios:")
            for scenario in gk_ph._scenario_tree._scenarios:
                print(scenario._name)
            print("")
            gk_ef = ExtensiveFormAlgorithm(gk_ph,
                                           options._ef_options,
                                           prefix="ef_")
            gk_ef.build_ef()
            print("Solving the xstar extensive form.")
            # Instance preprocessing is managed within the
            # ph object automatically when required for a
            # solve. Since we are solving the instances
            # outside of the ph object, we will inform it
            # that it should complete the instance
            # preprocessing early
            gk_ph._preprocess_scenario_instances()
            gk_ef.solve(io_options=\
                        {'output_fixed_variable_bounds':
                         options.write_fixed_variables})
            xstar_obj = gk_ef.objective
            # assuming this is the absolute gap
            xstar_obj_gap = gk_ef.gap
            """
            gk_ef = create_ef_instance(gk_ph._scenario_tree,
                                       generate_weighted_cvar=options.generate_weighted_cvar,
                                       cvar_weight=options.cvar_weight,
                                       risk_alpha=options.risk_alpha)
            print("Solving the xstar extensive form.")

            # Instance preprocessing is managed within the ph object
            # automatically when required for a solve. Since we are
            # solving the instances outside of the ph object, we will
            # inform it that it should complete the instance preprocessing
            # early
            gk_ph._preprocess_scenario_instances()

            ef_results = solve_ef(gk_ef, options)

            # as in the computation of xhat, the following is required to form a
            # solution to the extensive form in the scenario tree itself.
            gk_ph._scenario_tree.pullScenarioSolutionsFromInstances()
            gk_ph._scenario_tree.snapshotSolutionFromScenarios()

            # extract the objective function value corresponding to the
            # xstar solution, along with any gap information.

            xstar_obj = gk_ph._scenario_tree.findRootNode().computeExpectedNodeCost()
            # assuming this is the absolute gap
            xstar_obj_gap = gk_ef.solutions[0].gap# ef_results.solution(0).gap
            """

            print("Sample extensive form objective value=" + str(xstar_obj))

            # CVARHACK: if CPLEX barfed, keep trucking and bury our head
            # in the sand.
            if type(xstar_obj_gap) is UndefinedData:
                xstar_obj_bound = xstar_obj
                #EW#print("xstar_obj_bound= "+str(xstar_obj_bound))
            else:
                if sense == minimize:
                    xstar_obj_bound = xstar_obj - xstar_obj_gap
                else:
                    xstar_obj_bound = xstar_obj + xstar_obj_gap
                #EW#print("xstar_obj_bound= "+str(xstar_obj_bound))
                #EW#print("xstar_obj = "+str(xstar_obj))
                #EW#print("xstar_obj_gap = "+str(xstar_obj_gap))
            # TBD: ADD VERBOSE OUTPUT HERE

            # to get f(xhat) for this sample, fix the first-stage
            # variables and re-solve the extensive form.  note that the
            # fixing yields side-effects on the original gk_ef, but that
            # is fine as it isn't used after this point.
            print("Solving the extensive form given the xhat solution.")
            #xhat = pyomo.pysp.phboundbase.ExtractInternalNodeSolutionsforInner(xhat_ph)
            #
            # fix the first stage variables
            #
            gk_root_node = gk_ph._scenario_tree.findRootNode()
            #root_xhat = xhat[gk_root_node._name]
            root_xhat = xhat_ph._scenario_tree.findRootNode()._solution
            for variable_id in gk_root_node._standard_variable_ids:
                gk_root_node.fix_variable(variable_id, root_xhat[variable_id])

            # Push fixed variable statuses on instances (or
            # transmit to the phsolverservers), since we are not
            # calling the solve method on the ph object, we
            # need to do this manually
            gk_ph._push_fix_queue_to_instances()
            gk_ph._preprocess_scenario_instances()

            gk_ef.solve(io_options=\
                        {'output_fixed_variable_bounds':
                         options.write_fixed_variables})
            #ef_results = solve_ef(gk_ef, options)

            # we don't need the solution - just the objective value.
            #objective_name = "MASTER"
            #objective = gk_ef.find_component(objective_name)
            xstar_obj_given_xhat = gk_ef.objective

            print("Sample extensive form objective value given xhat=" +
                  str(xstar_obj_given_xhat))

            #g_supk_of_xhat.append(xstar_obj_given_xhat - xstar_obj_bound)
            if sense == minimize:
                g_supk_of_xhat.append(xstar_obj_given_xhat - xstar_obj_bound)
            else:
                g_supk_of_xhat.append(-xstar_obj_given_xhat + xstar_obj_bound)
            g_bar += g_supk_of_xhat[k - 1]
            sum_xstar_obj_given_xhat += xstar_obj_given_xhat

        finally:

            if gk_ph is not None:

                # we are using the PHCleanup function for
                # convenience, but we need to prevent it
                # from shutting down the scenario_instance_factory
                # as it is managed outside this function
                if gk_ph._scenario_tree._scenario_instance_factory is \
                   scenario_instance_factory:
                    gk_ph._scenario_tree._scenario_instance_factory = None
                PHCleanup(gk_ph)

    g_bar /= n_g
    # second pass for variance calculation (because we like storing
    # the g_supk)
    g_var = 0.0
    for k in range(0, n_g):
        print("g_supk_of_xhat[%d]=%12.6f" % (k + 1, g_supk_of_xhat[k]))
        g_var = g_var + (g_supk_of_xhat[k] - g_bar) * \
                (g_supk_of_xhat[k] - g_bar)
    if n_g != 1:
        # sample var
        g_var = g_var / (n_g - 1)
    print("")
    print("Raw results:")
    print("g_bar= " + str(g_bar))
    print("g_stddev= " + str(math.sqrt(g_var)))
    print("Average f(xhat)= " + str(sum_xstar_obj_given_xhat / n_g))

    if n_g in t_table_values:
        print("")
        print("Results summary:")
        t_table_entries = t_table_values[n_g]
        for key in sorted(iterkeys(t_table_entries)):
            print("Confidence interval width for alpha="+str(key)
                  +" is "+str(g_bar + (t_table_entries[key] * \
                                       math.sqrt(g_var) / \
                                       math.sqrt(n_g))))
    else:
        print(
            "No built-in t-table entries for " + str(n_g) +
            " degrees of freedom - cannot calculate confidence interval width")

    if options.write_xhat_solution:
        print("")
        print("xhat solution:")
        scenario_tree = xhat_ph._scenario_tree
        first_stage = scenario_tree._stages[0]
        root_node = first_stage._tree_nodes[0]
        for key, val in iteritems(root_node._solutions):
            for idx in val:
                if val[idx] != 0.0:
                    print("%s %s %s" % (str(key), str(idx), str(val[idx]())))

    scenario_count = len(full_scenario_tree._stages[-1]._tree_nodes)
    if options.append_file is not None:
        output_file = open(options.append_file, "a")
        output_file.write("\ninstancedirectory, " +
                          str(options.instance_directory) + ", seed, " +
                          str(options.random_seed) + ", N, " +
                          str(scenario_count) + ", hatn, " +
                          str(num_scenarios_for_solution) + ", n_g, " +
                          str(options.n_g) + ", Eoffofxhat, " +
                          str(sum_xstar_obj_given_xhat / n_g) + ", gbar, " +
                          str(g_bar) + ", sg, " + str(math.sqrt(g_var)) +
                          ", objforxhat, " + str(xhat_obj) + ", n," +
                          str(num_scenarios_per_sample))

        if n_g in t_table_values:
            t_table_entries = t_table_values[n_g]
            for key in sorted(iterkeys(t_table_entries)):
                output_file.write(" , alpha="+str(key)+" , "
                                  +str(g_bar + (t_table_entries[key] * \
                                                math.sqrt(g_var) / \
                                                math.sqrt(n_g))))

        if options.write_xhat_solution:
            output_file.write(" , ")
            scenario_tree = xhat_ph._scenario_tree
            first_stage = scenario_tree._stages[0]
            root_node = first_stage._tree_nodes[0]
            for key, val in iteritems(root_node._solutions):
                for idx in val:
                    if val[idx] != 0.0:
                        output_file.write(
                            "%s %s %s" % (str(key), str(idx), str(val[idx]())))
        output_file.close()
        print("")
        print("Results summary appended to file=" + options.append_file)

    xhat_ph.release_components()
Ejemplo n.º 2
0
def find_candidate(scenario_instance_factory, index_list,
                   num_scenarios_for_solution, full_scenario_tree, options):

    # create a ph object for finding the solution. we do this even if
    # we're solving the extensive form directly, mainly out of
    # convenience - we're leveraging the code in ph_for_bundle to
    # create the scenario tree and scenario instances.
    print("")
    print("Loading scenario instances and initializing "
          "scenario tree for xhat scenario bundle.")

    xhat_ph = None
    try:

        xhat_ph = ph_for_bundle(0, num_scenarios_for_solution,
                                scenario_instance_factory, full_scenario_tree,
                                index_list, options)

        xhat_obj = None

        sense = xhat_ph._scenario_tree._scenarios[0]._objective_sense
        if sense == minimize:
            print("We are solving a MINIMIZATION problem.")
        else:
            print("We are solving a MAXIMIZATION problem.")

        if not options.solve_xhat_with_ph:
            print("Creating the xhat extensive form.")
            print("")
            print("Composite scenarios:")
            for scenario in xhat_ph._scenario_tree._scenarios:
                print(scenario._name)
            print("")

            if options.verbose:
                print("Time=" + time.asctime())

            with ExtensiveFormAlgorithm(xhat_ph,
                                        options._ef_options,
                                        prefix="ef_") as ef:

                ef.build_ef()
                print("Solving the xhat extensive form.")
                # Instance preprocessing is managed within the
                # ph object automatically when required for a
                # solve. Since we are solving the instances
                # outside of the ph object, we will inform it
                # that it should complete the instance
                # preprocessing early
                xhat_ph._preprocess_scenario_instances()
                ef.solve(io_options=\
                         {'output_fixed_variable_bounds':
                          options.write_fixed_variables})
                xhat_obj = ef.objective
            """
            hatex_ef = create_ef_instance(
                xhat_ph._scenario_tree,
                verbose_output=options.verbose,
                generate_weighted_cvar=options.generate_weighted_cvar,
                cvar_weight=options.cvar_weight,
                risk_alpha=options.risk_alpha)

            if options.verbose:
                print("Time="+time.asctime())
            print("Solving the xhat extensive form.")

            # Instance preprocessing is managed within the ph object
            # automatically when required for a solve. Since we are
            # solving the instances outside of the ph object, we will
            # inform it that it should complete the instance preprocessing
            # early
            xhat_ph._preprocess_scenario_instances()

            ef_results = solve_ef(hatex_ef, options)

            if options.verbose:
                print("Loading extensive form solution.")
                print("Time="+time.asctime())

            # IMPT: the following method populates the _solution variables
            #       on the scenario tree nodes by forming an average of
            #       the corresponding variable values for all instances
            #       particpating in that node. if you don't do this, the
            #       scenario tree doesn't have the solution - and we need
            #       this below for variable fixing.
            if options.verbose:
                print("Computing extensive form solution from instances.")
                print("Time="+time.asctime())

            xhat_ph._scenario_tree.pullScenarioSolutionsFromInstances()
            xhat_ph._scenario_tree.snapshotSolutionFromScenarios()

            xhat_obj = xhat_ph._scenario_tree.findRootNode().computeExpectedNodeCost()
            """
            print("Extensive form objective value given xhat=" + str(xhat_obj))
        else:
            print("Solving for xhat via Progressive Hedging.")
            phretval = xhat_ph.solve()
            if phretval is not None:
                raise RuntimeError("No solution was obtained "
                                   "for scenario: " + phretval)
            # TBD - grab xhat_obj; complicated by the fact that PH may not
            #       have converged.
            # TBD - also not sure if PH calls
            #       snapshotSolutionFromAverages.
        print("The computation of xhat is complete - "
              "starting to compute confidence interval "
              "via sub-sampling.")

    finally:

        if xhat_ph is not None:

            # we are using the PHCleanup function for
            # convenience, but we need to prevent it
            # from shutting down the scenario_instance_factory
            # as it is managed outside this function
            xhat_ph._scenario_tree._scenario_instance_factory = None
            PHCleanup(xhat_ph)

    return xhat_ph