示例#1
0
def EXTERNAL_initialize_for_admm(manager, scenario):
    if manager.get_option("verbose"):
        print("Initializing scenario %s for admm algorithm" % (scenario.name))
    admm_block = Block(concrete=True)
    assert not hasattr(scenario._instance, ".admm")
    scenario._instance.add_component(".admm", admm_block)

    # Augment the objective with lagrangian and penalty terms
    # and weight the original objective by the scenario probability.
    # The langrangian and penalty terms will be computed after
    # the parameters are created.
    user_cost_expression = scenario._instance_cost_expression
    admm_block.cost_expression = Expression(initialize=\
        scenario.probability * user_cost_expression)
    admm_block.lagrangian_expression = Expression(initialize=0.0)
    admm_block.penalty_expression = Expression(initialize=0.0)
    # these are used in the objective, they can be toggled
    # between the expression above or something else (e.g., 0.0)
    admm_block.cost_term = Expression(initialize=admm_block.cost_expression)
    admm_block.lagrangian_term = Expression(
        initialize=admm_block.lagrangian_expression)
    admm_block.penalty_term = Expression(
        initialize=admm_block.penalty_expression)
    objective_direction = 1
    if manager.objective_sense == maximize:
        objective_direction = -1
    scenario._instance_objective.expr = \
        admm_block.cost_term + \
        admm_block.lagrangian_term * objective_direction + \
        admm_block.penalty_term * objective_direction

    # add objective parameters to admm block
    for tree_node in scenario.node_list[:-1]:
        assert not tree_node.is_leaf_node()
        node_block = Block(concrete=True)
        admm_block.add_component(tree_node.name, node_block)
        node_block.node_index_set = Set(ordered=True,
                                        initialize=sorted(
                                            tree_node._standard_variable_ids))
        node_block.z = Param(node_block.node_index_set,
                             initialize=0.0,
                             mutable=True)
        node_block.y = Param(node_block.node_index_set,
                             initialize=0.0,
                             mutable=True)
        node_block.rho = Param(node_block.node_index_set,
                               initialize=0.0,
                               mutable=True)

        for id_ in node_block.node_index_set:
            varname, index = tree_node._variable_ids[id_]
            var = scenario._instance.find_component(varname)[index]
            admm_block.lagrangian_expression.expr += \
                node_block.y[id_] * (var - node_block.z[id_])
            admm_block.penalty_expression.expr += \
                (node_block.rho[id_] / 2.0) * (var - node_block.z[id_])**2

    # The objective has changed so flag this if necessary.
    if manager.preprocessor is not None:
        manager.preprocessor.objective_updated[scenario.name] = True
示例#2
0
def EXTERNAL_initialize_for_admm(manager,
                                 scenario):
    if manager.get_option("verbose"):
        print("Initializing scenario %s for admm algorithm"
              % (scenario.name))
    admm_block = Block(concrete=True)
    assert not hasattr(scenario._instance, ".admm")
    scenario._instance.add_component(".admm", admm_block)

    # Augment the objective with lagrangian and penalty terms
    # and weight the original objective by the scenario probability.
    # The langrangian and penalty terms will be computed after
    # the parameters are created.
    user_cost_expression = scenario._instance_cost_expression
    admm_block.cost_expression = Expression(initialize=\
        scenario._probability * user_cost_expression)
    admm_block.lagrangian_expression = Expression(initialize=0.0)
    admm_block.penalty_expression = Expression(initialize=0.0)
    # these are used in the objective, they can be toggled
    # between the expression above or something else (e.g., 0.0)
    admm_block.cost_term = Expression(
        initialize=admm_block.cost_expression)
    admm_block.lagrangian_term = Expression(
        initialize=admm_block.lagrangian_expression)
    admm_block.penalty_term = Expression(
        initialize=admm_block.penalty_expression)
    objective_direction = 1
    if manager.objective_sense == maximize:
        objective_direction = -1
    scenario._instance_objective.expr = \
        admm_block.cost_term + \
        admm_block.lagrangian_term * objective_direction + \
        admm_block.penalty_term * objective_direction

    # add objective parameters to admm block
    for tree_node in scenario.node_list[:-1]:
        assert not tree_node.is_leaf_node()
        node_block = Block(concrete=True)
        admm_block.add_component(tree_node.name,
                                 node_block)
        node_block.index = Set(
            ordered=True,
            initialize=sorted(tree_node._standard_variable_ids))
        node_block.z = Param(node_block.index, initialize=0.0, mutable=True)
        node_block.y = Param(node_block.index, initialize=0.0, mutable=True)
        node_block.rho = Param(node_block.index, initialize=0.0, mutable=True)

        for id_ in node_block.index:
            varname, index = tree_node._variable_ids[id_]
            var = scenario._instance.find_component(varname)[index]
            admm_block.lagrangian_expression.expr += \
                node_block.y[id_] * (var - node_block.z[id_])
            admm_block.penalty_expression.expr += \
                (node_block.rho[id_] / 2.0) * (var - node_block.z[id_])**2

    # The objective has changed so flag this if necessary.
    if manager.preprocessor is not None:
        manager.preprocessor.objective_updated[scenario.name] = True
示例#3
0
文件: highpoint.py 项目: whart222/pao
def create_submodel_hp_block(instance):
    """
    Creates highpoint relaxation with the given specified model; does
    not include any submodel or block that is deactivated
    """
    block = Block(concrete=True)

    # create a component map to keep track of id() for the
    # original object and the referenced object
    block._map = ComponentMap()

    # get the objective for the master problem
    for c in instance.component_objects(Objective, descend_into=False):
        ref = Reference(c)
        block.add_component(c.name, ref)
        block._map[c] = ref[None]

    # get the variables of the model (if there are more submodels, then
    # extraneous variables may be added to the block)
    for c in instance.component_objects(Var,
                                        sort=True,
                                        descend_into=True,
                                        active=True):
        if c.is_indexed():
            ref = Reference(c[...])
            block.add_component(c.name, ref)
            block._map[c] = ref
        else:
            ref = Reference(c)
            block.add_component(c.name, ref)
            block._map[c] = ref[None]

    # get the constraints from the main model
    for c in instance.component_objects(Constraint,
                                        sort=True,
                                        descend_into=True,
                                        active=True):
        if c.is_indexed():
            ref = Reference(c[...])
            block.add_component(c.name, ref)
            block._map[c] = ref
        else:
            ref = Reference(c)
            block.add_component(c.name, ref)
            block._map[c] = ref[None]

    # deactivate the highpoint relaxation
    # block.deactivate()

    return block
示例#4
0
def _write_bundle_NL(worker,
                     bundle,
                     output_directory,
                     linking_suffix_name,
                     objective_suffix_name,
                     symbolic_solver_labels):

    assert os.path.exists(output_directory)

    bundle_instance = worker._bundle_binding_instance_map[bundle.name]
    assert not hasattr(bundle_instance, ".tmpblock")
    tmpblock = Block(concrete=True)
    bundle_instance.add_component(".tmpblock", tmpblock)

    #
    # linking variable suffix
    #
    tmpblock.add_component(linking_suffix_name,
                           Suffix(direction=Suffix.EXPORT))
    linking_suffix = getattr(tmpblock, linking_suffix_name)

    # Loop over all nodes for the bundle except the leaf nodes,
    # which have no blended variables
    scenario_tree = worker.scenario_tree
    for stage in bundle.scenario_tree.stages[:-1]:
        for _node in stage.nodes:
            # get the node of off the real scenario tree
            # as this has the linked variable information
            node = scenario_tree.get_node(_node.name)
            master_variable = bundle_instance.find_component(
                "MASTER_BLEND_VAR_"+str(node.name))
            for variable_id in node._standard_variable_ids:
                linking_suffix[master_variable[variable_id]] = variable_id

    #
    # objective weight suffix
    #
    tmpblock.add_component(objective_suffix_name,
                           Suffix(direction=Suffix.EXPORT))

    getattr(tmpblock, objective_suffix_name)[bundle_instance] = \
        bundle._probability

    output_filename = os.path.join(output_directory, str(bundle.name)+".nl")
    bundle_instance.write(
        output_filename,
        io_options={'symbolic_solver_labels': symbolic_solver_labels})

    bundle_instance.del_component(tmpblock)
示例#5
0
def _write_scenario_NL(worker,
                       scenario,
                       output_directory,
                       linking_suffix_name,
                       objective_suffix_name,
                       symbolic_solver_labels):

    assert os.path.exists(output_directory)
    instance = scenario._instance
    assert not hasattr(instance, ".tmpblock")
    tmpblock = Block(concrete=True)
    instance.add_component(".tmpblock", tmpblock)

    #
    # linking variable suffix
    #
    bySymbol = instance._ScenarioTreeSymbolMap.bySymbol
    tmpblock.add_component(linking_suffix_name,
                           Suffix(direction=Suffix.EXPORT))
    linking_suffix = getattr(tmpblock, linking_suffix_name)

    # Loop over all nodes for the scenario except the leaf node,
    # which has no blended variables
    for node in scenario._node_list[:-1]:
        for variable_id in node._standard_variable_ids:
            linking_suffix[bySymbol[variable_id]] = variable_id

    #
    # objective weight suffix
    #
    tmpblock.add_component(objective_suffix_name,
                           Suffix(direction=Suffix.EXPORT))
    getattr(tmpblock, objective_suffix_name)[instance] = \
        scenario._probability

    output_filename = os.path.join(output_directory,
                                   str(scenario.name)+".nl")
    instance.write(
        output_filename,
        io_options={'symbolic_solver_labels': symbolic_solver_labels})

    instance.del_component(tmpblock)
示例#6
0
def create_submodel_hp_block(instance):
    """
    Creates highpoint relaxation with the given specified model; does
    not include any submodel or block that is deactivated
    """
    block = Block(concrete=True)

    # get the objective for the master problem
    for c in instance.component_objects(Objective, descend_into=False):
        block.add_component(c.name, Reference(c))

    # get the variables of the model (if there are more submodels, then
    # extraneous variables may be added to the block)
    for c in instance.component_objects(Var,
                                        sort=True,
                                        descend_into=True,
                                        active=True):
        block.add_component(c.name, Reference(c))

    # get the constraints from the main model
    for c in instance.component_objects(Constraint,
                                        sort=True,
                                        descend_into=True,
                                        active=True):
        block.add_component(c.name, Reference(c))

    # deactivate the highpoint relaxation
    block.deactivate()

    return block
示例#7
0
def apply_basic_step(disjunctions_or_constraints):
    #
    # Basic steps only apply to XOR'd disjunctions
    #
    disjunctions = list(obj for obj in disjunctions_or_constraints
                        if obj.ctype == Disjunction)
    constraints = list(obj for obj in disjunctions_or_constraints
                       if obj.ctype == Constraint)
    for d in disjunctions:
        if not d.xor:
            raise ValueError(
                "Basic steps can only be applied to XOR'd disjunctions\n\t"
                "(raised by disjunction %s)" % (d.name, ))
        if not d.active:
            logger.warning("Warning: applying basic step to a previously "
                           "deactivated disjunction (%s)" % (d.name, ))

    ans = Block(concrete=True)
    ans.DISJUNCTIONS = Set(initialize=range(len(disjunctions)))
    ans.INDEX = Set(dimen=len(disjunctions),
                    initialize=_squish_singletons(
                        itertools.product(*tuple(
                            range(len(d.disjuncts)) for d in disjunctions))))

    #
    # Form the individual disjuncts for the new basic step
    #
    ans.disjuncts = Disjunct(ans.INDEX)
    for idx in ans.INDEX:
        #
        # Each source disjunct will be copied (cloned) into its own
        # subblock
        #
        ans.disjuncts[idx].src = Block(ans.DISJUNCTIONS)
        for i in ans.DISJUNCTIONS:
            tmp = _clone_all_but_indicator_vars(
                disjunctions[i].disjuncts[idx[i] if isinstance(idx, tuple
                                                               ) else idx])
            for k, v in list(tmp.component_map().items()):
                if v.parent_block() is not tmp:
                    # Skip indicator_var and binary_indicator_var
                    continue
                tmp.del_component(k)
                ans.disjuncts[idx].src[i].add_component(k, v)
        # Copy in the constraints corresponding to the improper disjunctions
        ans.disjuncts[idx].improper_constraints = ConstraintList()
        for constr in constraints:
            if constr.is_indexed():
                for indx in constr:
                    ans.disjuncts[idx].improper_constraints.add(
                        (constr[indx].lower, constr[indx].body,
                         constr[indx].upper))
                    constr[indx].deactivate()
            # need this so that we can take an improper basic step with a
            # ConstraintData
            else:
                ans.disjuncts[idx].improper_constraints.add(
                    (constr.lower, constr.body, constr.upper))
                constr.deactivate()

    #
    # Link the new disjunct indicator_var's to the original
    # indicator_var's.  Since only one of the new
    #
    NAME_BUFFER = {}
    ans.indicator_links = ConstraintList()
    for i in ans.DISJUNCTIONS:
        for j in range(len(disjunctions[i].disjuncts)):
            orig_var = disjunctions[i].disjuncts[j].indicator_var
            orig_binary_var = orig_var.get_associated_binary()
            ans.indicator_links.add(orig_binary_var == sum(
                ans.disjuncts[idx].binary_indicator_var for idx in ans.INDEX
                if (idx[i] if isinstance(idx, tuple) else idx) == j))
            # and throw on a Reference to original on the block
            for v in (orig_var, orig_binary_var):
                name_base = v.getname(fully_qualified=True,
                                      name_buffer=NAME_BUFFER)
                ans.add_component(unique_component_name(ans, name_base),
                                  Reference(v))

    # Form the new disjunction
    ans.disjunction = Disjunction(expr=[ans.disjuncts[i] for i in ans.INDEX])

    #
    # Deactivate the old disjunctions / disjuncts
    #
    for i in ans.DISJUNCTIONS:
        disjunctions[i].deactivate()
        for d in disjunctions[i].disjuncts:
            d._deactivate_without_fixing_indicator()

    return ans
示例#8
0
def _write_bundle_nl(worker,
                     bundle,
                     output_directory,
                     io_options):

    assert os.path.exists(output_directory)

    bundle_instance = worker._bundle_binding_instance_map[bundle.name]
    assert not hasattr(bundle_instance, ".schuripopt")
    tmpblock = Block(concrete=True)
    bundle_instance.add_component(".schuripopt", tmpblock)

    #
    # linking variable suffix
    #
    tmpblock.add_component(_variable_id_suffix_name,
                           Suffix(direction=Suffix.EXPORT,
                                  datatype=Suffix.INT))
    linking_suffix = getattr(tmpblock, _variable_id_suffix_name)

    # Loop over all nodes for the bundle except the leaf nodes,
    # which have no blended variables
    scenario_tree = worker.scenario_tree
    for stage in bundle.scenario_tree.stages[:-1]:
        for _node in stage.nodes:
            # get the node of off the real scenario tree
            # as this has the linked variable information
            node = scenario_tree.get_node(_node.name)
            node_name = node.name
            master_variable = bundle_instance.find_component(
                "MASTER_BLEND_VAR_"+str(node.name))
            for variable_id in node._standard_variable_ids:
                # Assumes ASL uses 4-byte, signed integers to store suffixes,
                # and we need positive suffix values
                linking_suffix[master_variable[variable_id]] = \
                    scenario_tree_id_to_pint32(node_name, variable_id)
    # make sure the conversion from scenario tree id to int
    # did not have any collisions
    _ids = list(linking_suffix.values())
    assert len(_ids) == len(set(_ids))

    #
    # objective weight suffix
    #
    tmpblock.add_component(_objective_weight_suffix_name,
                           Suffix(direction=Suffix.EXPORT))
    getattr(tmpblock, _objective_weight_suffix_name)[bundle_instance] = \
        bundle.probability

    # take care to disable any advanced preprocessing flags since we
    # are not going through the scenario tree manager solver interface
    # TODO: resolve this preprocessing mess
    block_attrs = []
    for block in bundle_instance.block_data_objects(active=True):
        attrs = []
        for attr_name in ("_gen_obj_ampl_repn",
                          "_gen_con_ampl_repn"):
            if hasattr(block, attr_name):
                attrs.append((attr_name, getattr(block, attr_name)))
                setattr(block, attr_name, True)
        if len(attrs):
            block_attrs.append((block, attrs))

    output_filename = os.path.join(output_directory,
                                   str(bundle.name)+".nl")
    # write the model and obtain the symbol_map
    _, smap_id = bundle_instance.write(
        output_filename,
        format=ProblemFormat.nl,
        io_options=io_options)
    symbol_map = bundle_instance.solutions.symbol_map[smap_id]

    # reset preprocessing flags
    # TODO: resolve this preprocessing mess
    for block, attrs in block_attrs:
        for attr_name, attr_val in attrs:
            setattr(block, attr_name, attr_val)

    bundle_instance.del_component(tmpblock)

    return output_filename, symbol_map
示例#9
0
def _write_scenario_nl(worker,
                       scenario,
                       output_directory,
                       io_options):

    assert os.path.exists(output_directory)
    instance = scenario._instance
    assert not hasattr(instance, ".schuripopt")
    tmpblock = Block(concrete=True)
    instance.add_component(".schuripopt", tmpblock)

    #
    # linking variable suffix
    #
    bySymbol = instance._ScenarioTreeSymbolMap.bySymbol
    tmpblock.add_component(_variable_id_suffix_name,
                           Suffix(direction=Suffix.EXPORT,
                                  datatype=Suffix.INT))
    linking_suffix = getattr(tmpblock, _variable_id_suffix_name)

    # Loop over all nodes for the scenario except the leaf node,
    # which has no blended variables
    for node in scenario._node_list[:-1]:
        node_name = node.name
        for variable_id in node._standard_variable_ids:
            # Assumes ASL uses 4-byte, signed integers to store suffixes,
            # and we need positive suffix values
            linking_suffix[bySymbol[variable_id]] = \
                scenario_tree_id_to_pint32(node_name, variable_id)
    # make sure the conversion from scenario tree id to int
    # did not have any collisions
    _ids = list(linking_suffix.values())
    assert len(_ids) == len(set(_ids))

    #
    # objective weight suffix
    #
    tmpblock.add_component(_objective_weight_suffix_name,
                           Suffix(direction=Suffix.EXPORT))
    getattr(tmpblock, _objective_weight_suffix_name)[instance] = \
        scenario.probability

    # take care to disable any advanced preprocessing flags since we
    # are not going through the scenario tree manager solver interface
    # TODO: resolve this preprocessing mess
    block_attrs = []
    for block in instance.block_data_objects(active=True):
        attrs = []
        for attr_name in ("_gen_obj_ampl_repn",
                          "_gen_con_ampl_repn"):
            if hasattr(block, attr_name):
                attrs.append((attr_name, getattr(block, attr_name)))
                setattr(block, attr_name, True)
        if len(attrs):
            block_attrs.append((block, attrs))

    output_filename = os.path.join(output_directory,
                                   str(scenario.name)+".nl")

    # write the model and obtain the symbol_map
    _, smap_id = instance.write(
        output_filename,
        format=ProblemFormat.nl,
        io_options=io_options)
    symbol_map = instance.solutions.symbol_map[smap_id]

    # reset preprocessing flags
    # TODO: resolve this preprocessing mess
    for block, attrs in block_attrs:
        for attr_name, attr_val in attrs:
            setattr(block, attr_name, attr_val)

    instance.del_component(tmpblock)

    return output_filename, symbol_map
示例#10
0
文件: schuripopt.py 项目: Pyomo/pyomo
def _write_bundle_nl(worker,
                     bundle,
                     output_directory,
                     io_options):

    assert os.path.exists(output_directory)

    bundle_instance = worker._bundle_binding_instance_map[bundle.name]
    assert not hasattr(bundle_instance, ".schuripopt")
    tmpblock = Block(concrete=True)
    bundle_instance.add_component(".schuripopt", tmpblock)

    #
    # linking variable suffix
    #
    tmpblock.add_component(_variable_id_suffix_name,
                           Suffix(direction=Suffix.EXPORT,
                                  datatype=Suffix.INT))
    linking_suffix = getattr(tmpblock, _variable_id_suffix_name)

    # Loop over all nodes for the bundle except the leaf nodes,
    # which have no blended variables
    scenario_tree = worker.scenario_tree
    for stage in bundle.scenario_tree.stages[:-1]:
        for _node in stage.nodes:
            # get the node of off the real scenario tree
            # as this has the linked variable information
            node = scenario_tree.get_node(_node.name)
            node_name = node.name
            master_variable = bundle_instance.find_component(
                "MASTER_BLEND_VAR_"+str(node.name))
            for variable_id in node._standard_variable_ids:
                # Assumes ASL uses 4-byte, signed integers to store suffixes,
                # and we need positive suffix values
                linking_suffix[master_variable[variable_id]] = \
                    scenario_tree_id_to_pint32(node_name, variable_id)
    # make sure the conversion from scenario tree id to int
    # did not have any collisions
    _ids = list(linking_suffix.values())
    assert len(_ids) == len(set(_ids))

    #
    # objective weight suffix
    #
    tmpblock.add_component(_objective_weight_suffix_name,
                           Suffix(direction=Suffix.EXPORT))
    getattr(tmpblock, _objective_weight_suffix_name)[bundle_instance] = \
        bundle.probability

    # take care to disable any advanced preprocessing flags since we
    # are not going through the scenario tree manager solver interface
    # TODO: resolve this preprocessing mess
    block_attrs = []
    for block in bundle_instance.block_data_objects(active=True):
        attrs = []
        for attr_name in ("_gen_obj_repn",
                          "_gen_con_repn"):
            if hasattr(block, attr_name):
                attrs.append((attr_name, getattr(block, attr_name)))
                setattr(block, attr_name, True)
        if len(attrs):
            block_attrs.append((block, attrs))

    output_filename = os.path.join(output_directory,
                                   str(bundle.name)+".nl")
    # write the model and obtain the symbol_map
    _, smap_id = bundle_instance.write(
        output_filename,
        format=ProblemFormat.nl,
        io_options=io_options)
    symbol_map = bundle_instance.solutions.symbol_map[smap_id]

    # reset preprocessing flags
    # TODO: resolve this preprocessing mess
    for block, attrs in block_attrs:
        for attr_name, attr_val in attrs:
            setattr(block, attr_name, attr_val)

    bundle_instance.del_component(tmpblock)

    return output_filename, symbol_map
示例#11
0
文件: schuripopt.py 项目: Pyomo/pyomo
def _write_scenario_nl(worker,
                       scenario,
                       output_directory,
                       io_options):

    assert os.path.exists(output_directory)
    instance = scenario._instance
    assert not hasattr(instance, ".schuripopt")
    tmpblock = Block(concrete=True)
    instance.add_component(".schuripopt", tmpblock)

    #
    # linking variable suffix
    #
    bySymbol = instance._ScenarioTreeSymbolMap.bySymbol
    tmpblock.add_component(_variable_id_suffix_name,
                           Suffix(direction=Suffix.EXPORT,
                                  datatype=Suffix.INT))
    linking_suffix = getattr(tmpblock, _variable_id_suffix_name)

    # Loop over all nodes for the scenario except the leaf node,
    # which has no blended variables
    for node in scenario._node_list[:-1]:
        node_name = node.name
        for variable_id in node._standard_variable_ids:
            # Assumes ASL uses 4-byte, signed integers to store suffixes,
            # and we need positive suffix values
            linking_suffix[bySymbol[variable_id]] = \
                scenario_tree_id_to_pint32(node_name, variable_id)
    # make sure the conversion from scenario tree id to int
    # did not have any collisions
    _ids = list(linking_suffix.values())
    assert len(_ids) == len(set(_ids))

    #
    # objective weight suffix
    #
    tmpblock.add_component(_objective_weight_suffix_name,
                           Suffix(direction=Suffix.EXPORT))
    getattr(tmpblock, _objective_weight_suffix_name)[instance] = \
        scenario.probability

    # take care to disable any advanced preprocessing flags since we
    # are not going through the scenario tree manager solver interface
    # TODO: resolve this preprocessing mess
    block_attrs = []
    for block in instance.block_data_objects(active=True):
        attrs = []
        for attr_name in ("_gen_obj_repn",
                          "_gen_con_repn"):
            if hasattr(block, attr_name):
                attrs.append((attr_name, getattr(block, attr_name)))
                setattr(block, attr_name, True)
        if len(attrs):
            block_attrs.append((block, attrs))

    output_filename = os.path.join(output_directory,
                                   str(scenario.name)+".nl")

    # write the model and obtain the symbol_map
    _, smap_id = instance.write(
        output_filename,
        format=ProblemFormat.nl,
        io_options=io_options)
    symbol_map = instance.solutions.symbol_map[smap_id]

    # reset preprocessing flags
    # TODO: resolve this preprocessing mess
    for block, attrs in block_attrs:
        for attr_name, attr_val in attrs:
            setattr(block, attr_name, attr_val)

    instance.del_component(tmpblock)

    return output_filename, symbol_map