Esempio n. 1
0
 def test_ama_creator(self):
     options = _get_base_options()
     ama_options = {
         "EF-2stage": True,
     }
     ama_options.update(options['opt'])
     ama_object = ama.from_module(refmodelname,
                                  options=ama_options,
                                  use_command_line=False)
Esempio n. 2
0
 def test_ama_running(self):
     options = _get_base_options()
     ama_options = {"EF-2stage": True}
     ama_options.update(options['opt'])
     ama_object = ama.from_module(refmodelname,
                                  ama_options,
                                  use_command_line=False)
     ama_object.run()
     obj = round_pos_sig(ama_object.EF_Obj, 2)
     self.assertEqual(obj, -130000)
Esempio n. 3
0
def main():
    solution_files = {"first_stage_solution":"farmer_first_stage.csv",
                      }
    ama_options = {"EF-2stage": True,   # We are solving directly the EF
                   "write_solution":solution_files}
    #The module can be a local file
    ama = amalgomator.from_module("afarmer", ama_options)
    ama.run()
    print("first_stage_solution=", ama.first_stage_solution)
    print("inner bound=", ama.best_inner_bound)
    print("outer bound=", ama.best_outer_bound)
Esempio n. 4
0
def xhat_generator_farmer(scenario_names, solvername="gurobi", solver_options=None, crops_multiplier=1):
    '''Farmer example applied to sequential sampling. Given scenario names and
    options, create the scenarios and compute the xhat that is minimizing the
    approximate probleme associatd with these scenarios.

    Parameters
    ----------
    scenario_names: int
        Names of the scenario we use
    solvername: str, optional
        Name of the solver used. The default is "gurobi".
    solver_options: dict, optional
        Solving options. The default is None.
    crops_multiplier: int, optional
        A parameter of the farmer model. The default is 1.

    Returns
    -------
    xhat: xhat object (dict containing a 'ROOT' key with a np.array)
        A generated xhat.

    '''
    num_scens = len(scenario_names)
    
    ama_options = { "EF-2stage": True,
                    "EF_solver_name": solvername,
                    "EF_solver_options": solver_options,
                    "use_integer": False,
                    "crops_multiplier": crops_multiplier,
                    "num_scens": num_scens,
                    "_mpisppy_probability": 1/num_scens,
                    }
    #We use from_module to build easily an Amalgomator object
    ama = amalgomator.from_module("mpisppy.tests.examples.farmer",
                                  ama_options,use_command_line=False)
    #Correcting the building by putting the right scenarios.
    ama.scenario_names = scenario_names
    ama.run()
    
    # get the xhat
    xhat = sputils.nonant_cache_from_ef(ama.ef)

    return xhat
Esempio n. 5
0
def xhat_generator_apl1p(scenario_names,
                         solvername="gurobi",
                         solver_options=None):
    '''
    For sequential sampling.
    Takes scenario names as input and provide the best solution for the 
        approximate problem associated with the scenarios.
    Parameters
    ----------
    scenario_names: int
        Names of the scenario we use
    solvername: str, optional
        Name of the solver used. The default is "gurobi"
    solver_options: dict, optional
        Solving options. The default is None.

    Returns
    -------
    xhat: str
        A generated xhat, solution to the approximate problem induced by scenario_names.

    '''
    num_scens = len(scenario_names)

    ama_options = {
        "EF-2stage": True,
        "EF_solver_name": solvername,
        "EF_solver_options": solver_options,
        "num_scens": num_scens,
        "_mpisppy_probability": 1 / num_scens,
    }
    #We use from_module to build easily an Amalgomator object
    ama = amalgomator.from_module("mpisppy.tests.examples.apl1p",
                                  ama_options,
                                  use_command_line=False)
    #Correcting the building by putting the right scenarios.
    ama.scenario_names = scenario_names
    ama.run()

    # get the xhat
    xhat = sputils.nonant_cache_from_ef(ama.ef)

    return xhat
Esempio n. 6
0
def main():
    solution_files = {
        "first_stage_solution": "uc_first_stage.csv",
        #"tree_solution":"uc_ama_full_solution"
        #It takes too long to right the full solution
    }
    ama_options = {
        "2stage": True,  # 2stage vs. mstage
        "cylinders": ['ph', 'xhatshuffle', 'lagranger'],
        "extensions": ['fixer'],
        "id_fix_list_fct":
        id_fix_list_fct,  #Needed for fixer, but not passed in baseparsers
        "write_solution": solution_files
    }
    ama = amalgomator.from_module("uc_funcs", ama_options)
    ama.run()
    if ama.on_hub:
        print("first_stage_solution=", ama.first_stage_solution)
        print("inner bound=", ama.best_inner_bound)
        print("outer bound=", ama.best_outer_bound)
Esempio n. 7
0
    ama_extraargs.add_argument(
        "--MMW-num-batches",
        help="number of batches used for MMW confidence interval (default 1)",
        dest="num_batches",
        type=int,
        default=1)

    ama_extraargs.add_argument(
        "--MMW-batch-size",
        help="batch size used for MMW confidence interval (default None)",
        dest="batch_size",
        type=int,
        default=None)  #None means take batch_size=num_scens

    ama_object = ama.from_module(refmodel,
                                 ama_options,
                                 extraargs=ama_extraargs)
    ama_object.run()

    if global_rank == 0:
        print("inner bound=", ama_object.best_inner_bound)
        # This the xhat of the left term of LHS of MMW (9)
        print("outer bound=", ama_object.best_outer_bound)

    ########### get the nonants (the xhat)
    nonant_cache = sputils.nonant_cache_from_ef(ama_object.ef)
    ciutils.write_xhat(nonant_cache, path="xhat.npy")

    #Set parameters for run()

    options = ama_object.options
Esempio n. 8
0
if __name__ == "__main__":
    bfs = [4, 3, 2]
    num_scens = np.prod(bfs)  #To check with a full tree
    ama_options = {
        "EF-mstage": True,
        "EF_solver_name": "gurobi_direct",
        "num_scens": num_scens,
        "_mpisppy_probability": 1 / num_scens,
        "BFs": bfs,
        "mudev": 0,
        "sigmadev": 80
    }
    refmodel = "mpisppy.tests.examples.aircond_submodels"  # WARNING: Change this in SPInstances
    #We use from_module to build easily an Amalgomator object
    ama = amalgomator.from_module(refmodel,
                                  ama_options,
                                  use_command_line=False)
    ama.run()
    print(f"inner bound=", ama.best_inner_bound)
    print(f"outer bound=", ama.best_outer_bound)

    from mpisppy.confidence_intervals.mmw_ci import MMWConfidenceIntervals
    options = ama.options
    options['solver_options'] = options['EF_solver_options']
    xhat = sputils.nonant_cache_from_ef(ama.ef)['ROOT']

    num_batches = 10
    batch_size = 100

    mmw = MMWConfidenceIntervals(refmodel,
                                 options,
Esempio n. 9
0
def xhat_generator_aircond(scenario_names,
                           solvername="gurobi",
                           solver_options=None,
                           BFs=[3, 2, 3],
                           mudev=0,
                           sigmadev=40,
                           start_seed=0):
    '''
    For sequential sampling.
    Takes scenario names as input and provide the best solution for the 
        approximate problem associated with the scenarios.
    Parameters
    ----------
    scenario_names: int
        Names of the scenario we use
    solvername: str, optional
        Name of the solver used. The default is "gurobi"
    solver_options: dict, optional
        Solving options. The default is None.
    BFs: list, optional
        Branching factors of the scenario 3. The default is [3,2,3] 
        (a 4 stage model with 18 different scenarios)
    mudev: float, optional
        The average deviation of demand between two stages; The default is 0.
    sigma_dev: float, optional
        The standard deviation from mudev for the demand difference between
        two stages. The default is 40.
    start_seed: int, optional
        The starting seed, used to create different sample scenario trees.
        The default is 0.

    Returns
    -------
    xhat: str
        A generated xhat, solution to the approximate problem induced by scenario_names.
        
    NOTE: This tool only works when the file is in mpisppy. In SPInstances, 
            you must change the from_module line.

    '''
    num_scens = len(scenario_names)

    ama_options = {
        "EF-mstage": True,
        "EF_solver_name": solvername,
        "EF_solver_options": solver_options,
        "num_scens": num_scens,
        "_mpisppy_probability": 1 / num_scens,
        "BFs": BFs,
        "mudev": mudev,
        "start_seed": start_seed,
        "sigmadev": sigmadev
    }
    #We use from_module to build easily an Amalgomator object
    ama = amalgomator.from_module("mpisppy.tests.examples.aircond_submodels",
                                  ama_options,
                                  use_command_line=False)
    #Correcting the building by putting the right scenarios.
    ama.scenario_names = scenario_names
    ama.verbose = False
    ama.run()

    # get the xhat
    xhat = sputils.nonant_cache_from_ef(ama.ef)

    return {'ROOT': xhat['ROOT']}
Esempio n. 10
0
    return xhats, seed


if __name__ == "__main__":
    BFs = [3, 2, 4, 4]
    num_scens = np.prod(BFs)
    mname = "mpisppy.tests.examples.aircond_submodels"

    ama_options = {
        "EF-mstage": True,
        "num_scens": num_scens,
        "_mpisppy_probability": 1 / num_scens,
        "BFs": BFs,
    }
    #We use from_module to build easily an Amalgomator object
    ama = amalgomator.from_module(mname, ama_options, use_command_line=False)
    ama.run()

    # get the xhat
    xhat_one = sputils.nonant_cache_from_ef(ama.ef)['ROOT']

    #----------Find a feasible solution for a single scenario-------------
    scenario = ama.ef.scen0
    seed = sputils.number_of_nodes(BFs)
    options = dict()  #We take default aircond options

    xhats, seed = feasible_solution(mname, scenario, xhat_one, BFs, seed,
                                    options)
    print(xhats)

    #----------Find feasible solutions for every scenario ------------
Esempio n. 11
0
            return None
        else:
            if verbose and self.cylinder_rank == 0:
                print("  Feasible xhat found")
            return self.Eobjective(verbose=verbose)


if __name__ == "__main__":
    #==============================
    # hardwired by dlw for debugging (this main is like MMW, but strange)
    import mpisppy.tests.examples.farmer as refmodel
    import mpisppy.utils.amalgomator as ama

    # do the right term of MMW (9) using the first scenarios
    ama_options = {"EF-2stage": True}  # 2stage vs. mstage
    ama_object = ama.from_module("mpisppy.tests.examples.farmer", ama_options)
    ama_object.run()
    print(f"inner bound=", ama_object.best_inner_bound)
    # This the right term of LHS of MMW (9)
    print(f"outer bound=", ama_object.best_outer_bound)

    ############### now get an xhat using different scenarios
    # (use use the ama args to get problem parameters)
    ScenCount = ama_object.options['num_scens']
    scenario_creator = refmodel.scenario_creator
    scenario_denouement = refmodel.scenario_denouement
    crops_multiplier = ama_object.options['crops_multiplier']
    solvername = ama_object.options['EF_solver_name']

    scenario_creator_kwargs = {
        "use_integer": False,
Esempio n. 12
0
def gap_estimators(xhat_one,
                   mname, 
                   solving_type="EF-2stage",
                   scenario_names=None,
                   sample_options=None,
                   ArRP=1,
                   scenario_creator_kwargs={}, 
                   scenario_denouement=None,
                   solvername='gurobi', 
                   solver_options=None,
                   verbose=True,
                   objective_gap=False
                   ):
    ''' Given a xhat, scenario names, a scenario creator and options, 
    gap_estimators creates a scenario tree and the associatd estimators 
    G and s from §2 of [bm2011].
    Returns G and s evaluated at xhat.
    If ArRP>1, G and s are pooled, from a number ArRP of estimators,
        computed with different scenario trees.
    

    Parameters
    ----------
    xhat_one : dict
        A candidate first stage solution
    mname: str
        Name of the reference model, e.g. 'mpisppy.tests.examples.farmer'.
    solving_type: str, optional
        The way we solve the approximate problem. Can be "EF-2stage" (default)
        or "EF-mstage".
    scenario_names: list, optional
        List of scenario names used to compute G_n and s_n. Default is None
        Must be specified for 2 stage, but can be missing for multistage
    sample_options: dict, optional
        Only for multistage. Must contain a 'seed' and a 'BFs' attribute,
        specifying the starting seed and the branching factors 
        of the scenario tree
    ArRP:int,optional
        Number of batches (we create a ArRP model). Default is 1 (one batch).
    scenario_creator_kwargs: dict, optional
        Additional arguments for scenario_creator. Default is {}
    scenario_denouement: function, optional
        Function to run after scenario creation. Default is None.
    solvername : str, optional
        Solver. Default is 'gurobi'
    solver_options: dict, optional
        Solving options. Default is None
    verbose: bool, optional
        Should it print the gap estimator ? Default is True
    objective_gap: bool, optional
        Returns a gap estimate around approximate objective value

    BFs: list, optional
        Only for multistage. List of branching factors of the sample scenario tree.

    Returns
    -------
    G_k and s_k, gap estimator and associated standard deviation estimator.

    '''
    if solving_type not in ["EF-2stage","EF-mstage"]:
        raise RuntimeError("Only EF solve for the approximate problem is supported yet.")
    else:
        is_multi = (solving_type=="EF-mstage")
    
    
        
    if is_multi:
        try:
            BFs = sample_options['BFs']
            start = sample_options['seed']
        except (TypeError,KeyError,RuntimeError):
            raise RuntimeError('For multistage problems, sample_options must be a dict with BFs and seed attributes.')
    else:
        start = sputils.extract_num(scenario_names[0])
    if ArRP>1: #Special case : ArRP, G and s are pooled from r>1 estimators.
        if is_multi:
            raise RuntimeError("Pooled estimators are not supported for multistage problems yet.")
        n = len(scenario_names)
        if(n%ArRP != 0):
            raise RuntimeWarning("You put as an input a number of scenarios"+\
                                 f" which is not a mutliple of {ArRP}.")
            n = n- n%ArRP
        G =[]
        s = []

        for k in range(ArRP):
            scennames = scenario_names[k*(n//ArRP):(k+1)*(n//ArRP)]
            tmp = gap_estimators(xhat_one, mname,
                                   solvername=solvername,
                                   scenario_names=scennames, ArRP=1,
                                   scenario_creator_kwargs=scenario_creator_kwargs,
                                   scenario_denouement=scenario_denouement,
                                   solver_options=solver_options,
                                   solving_type=solving_type
                                   )
            G.append(tmp['G'])
            s.append(tmp['s']) 

        #Pooling
        G = np.mean(G)
        s = np.linalg.norm(s)/np.sqrt(n//ArRP)
        return {"G": G, "s": s, "seed": start}
    

    #A1RP
    
    #We start by computing the optimal solution to the approximate problem induced by our scenarios
    if is_multi:
        #Sample a scenario tree: this is a subtree, but starting from stage 1
        samp_tree = sample_tree.SampleSubtree(mname,
                                              xhats =[],
                                              root_scen=None,
                                              starting_stage=1, 
                                              BFs=BFs,
                                              seed=start, 
                                              options=scenario_creator_kwargs,
                                              solvername=solvername,
                                              solver_options=solver_options)
        samp_tree.run()
        start += sputils.number_of_nodes(BFs)
        ama_object = samp_tree.ama
    else:
        #We use amalgomator to do it

        ama_options = dict(scenario_creator_kwargs)
        ama_options['start'] = start
        ama_options['num_scens'] = len(scenario_names)
        ama_options['EF_solver_name'] = solvername
        ama_options['EF_solver_options'] = solver_options
        ama_options[solving_type] = True
        ama_object = ama.from_module(mname, ama_options,use_command_line=False)
        ama_object.scenario_names = scenario_names
        ama_object.verbose = False
        ama_object.run()
        start += len(scenario_names)
        
    #Optimal solution of the approximate problem
    zstar = ama_object.best_outer_bound
    #Associated policies
    xstars = sputils.nonant_cache_from_ef(ama_object.ef)
    
    #Then, we evaluate the fonction value induced by the scenario at xstar.
    
    if is_multi:
        # Find feasible policies (i.e. xhats) for every non-leaf nodes
        if len(samp_tree.ef._ef_scenario_names)>1:
            local_scenarios = {sname:getattr(samp_tree.ef,sname) for sname in samp_tree.ef._ef_scenario_names}
        else:
            local_scenarios = {samp_tree.ef._ef_scenario_names[0]:samp_tree.ef}
        xhats,start = sample_tree.walking_tree_xhats(mname,
                                                    local_scenarios,
                                                    xhat_one['ROOT'],
                                                    BFs,
                                                    start,
                                                    scenario_creator_kwargs,
                                                    solvername=solvername,
                                                    solver_options=solver_options)
        
        #Compute then the average function value with this policy
        scenario_creator_kwargs = samp_tree.ama.kwargs
        all_nodenames = sputils.create_nodenames_from_BFs(BFs)
    else:
        #In a 2 stage problem, the only non-leaf is the ROOT node
        xhats = xhat_one
        all_nodenames = None
    
    xhat_eval_options = {"iter0_solver_options": None,
                         "iterk_solver_options": None,
                         "display_timing": False,
                         "solvername": solvername,
                         "verbose": False,
                         "solver_options":solver_options}
    ev = xhat_eval.Xhat_Eval(xhat_eval_options,
                            scenario_names,
                            ama_object.scenario_creator,
                            scenario_denouement,
                            scenario_creator_kwargs=scenario_creator_kwargs,
                            all_nodenames = all_nodenames)
    #Evaluating xhat and xstar and getting the value of the objective function 
    #for every (local) scenario
    ev.evaluate(xhats)
    objs_at_xhat = ev.objs_dict
    ev.evaluate(xstars)
    objs_at_xstar = ev.objs_dict
    
    eval_scen_at_xhat = []
    eval_scen_at_xstar = []
    scen_probs = []
    for k,s in ev.local_scenarios.items():
        eval_scen_at_xhat.append(objs_at_xhat[k])
        eval_scen_at_xstar.append(objs_at_xstar[k])
        scen_probs.append(s._mpisppy_probability)

    
    scen_gaps = np.array(eval_scen_at_xhat)-np.array(eval_scen_at_xstar)
    local_gap = np.dot(scen_gaps,scen_probs)
    local_ssq = np.dot(scen_gaps**2,scen_probs)
    local_prob_sqnorm = np.linalg.norm(scen_probs)**2
    local_obj_at_xhat = np.dot(eval_scen_at_xhat,scen_probs)
    local_estim = np.array([local_gap,local_ssq,local_prob_sqnorm,local_obj_at_xhat])
    global_estim = np.zeros(4)
    ev.mpicomm.Allreduce(local_estim, global_estim, op=mpi.SUM) 
    G,ssq, prob_sqnorm,obj_at_xhat = global_estim
    if global_rank==0 and verbose:
        print(f"G = {G}")
    sample_var = (ssq - G**2)/(1-prob_sqnorm) #Unbiased sample variance
    s = np.sqrt(sample_var)
    
    use_relative_error = (np.abs(zstar)>1)
    G = correcting_numeric(G,objfct=obj_at_xhat,
                           relative_error=use_relative_error)
    if objective_gap:
        if is_multi:
            return {"G":G,"s":s,"zhats": [obj_at_xhat], "seed":start} 
        else:
            return {"G":G,"s":s,"zhats": eval_scen_at_xhat, "seed":start} 
    else:
        return {"G":G,"s":s,"seed":start}