Beispiel #1
0
def test_init(message_test_mp):
    scen = Scenario(message_test_mp, **SCENARIO['dantzig'])

    scen = scen.clone('foo', 'bar')
    scen.check_out()
    MACRO.initialize(scen)
    scen.commit('foo')
    scen.solve()

    assert np.isclose(scen.var('OBJ')['lvl'], 153.675)
    assert 'mapping_macro_sector' in scen.set_list()
    assert 'aeei' in scen.par_list()
    assert 'DEMAND' in scen.var_list()
    assert 'COST_ACCOUNTING_NODAL' in scen.equ_list()
def test_init(message_test_mp):
    scen = Scenario(message_test_mp, **SCENARIO["dantzig"])

    scen = scen.clone("foo", "bar")
    scen.check_out()
    MACRO.initialize(scen)
    scen.commit("foo")
    scen.solve(quiet=True)

    assert np.isclose(scen.var("OBJ")["lvl"], 153.675)
    assert "mapping_macro_sector" in scen.set_list()
    assert "aeei" in scen.par_list()
    assert "DEMAND" in scen.var_list()
    assert "COST_ACCOUNTING_NODAL" in scen.equ_list()
Beispiel #3
0
def apply_spec(
    scenario: Scenario,
    spec: Mapping[str, ScenarioInfo],
    data: Callable = None,
    **options,
):
    """Apply `spec` to `scenario`.

    Parameters
    ----------
    spec
        A 'specification': :class:`dict` with 'require', 'remove', and 'add' keys and
        :class:`.ScenarioInfo` objects as values.
    data : callable, optional
        Function to add data to `scenario`. `data` can either manipulate the scenario
        directly, or return a :class:`dict` compatible with :func:`.add_par_data`.

    Other parameters
    ----------------
    dry_run : bool
        Don't modify `scenario`; only show what would be done. Default :obj:`False`.
        Exceptions will still be raised if the elements from ``spec['required']`` are
        missing; this serves as a check that the scenario has the required features for
        applying the spec.
    fast : bool
        Do not remove existing parameter data; increases speed on large scenarios.
    quiet : bool
        Only show log messages at level ``ERROR`` and higher. If :obj:`False` (default),
        show log messages at level ``DEBUG`` and higher.
    message : str
        Commit message.

    See also
    --------
    .add_par_data
    .strip_par_data
    .Code
    .ScenarioInfo
    """
    dry_run = options.get("dry_run", False)

    log.setLevel(logging.ERROR if options.get("quiet", False) else logging.DEBUG)

    if not dry_run:
        try:
            scenario.remove_solution()
        except ValueError:
            pass
        maybe_check_out(scenario)

    dump: Dict[str, pd.DataFrame] = {}  # Removed data

    for set_name in scenario.set_list():
        # Check whether this set is mentioned at all in the spec
        if 0 == sum(map(lambda info: len(info.set[set_name]), spec.values())):
            # Not mentioned; don't do anything
            continue

        log.info(f"Set {repr(set_name)}")

        # Base contents of the set
        base_set = scenario.set(set_name)
        # Unpack a multi-dimensional/indexed set to a list of tuples
        base = (
            list(base_set.itertuples(index=False))
            if isinstance(base_set, pd.DataFrame)
            else base_set.tolist()
        )

        log.info(f"  {len(base)} elements")
        # log.debug(', '.join(map(repr, base)))  # All elements; verbose

        # Check for required elements
        require = spec["require"].set[set_name]
        log.info(f"  Check {len(require)} required elements")

        # Raise an exception about the first missing element
        missing = list(filter(lambda e: e not in base, require))
        if len(missing):
            log.error(f"  {len(missing)} elements not found: {repr(missing)}")
            raise ValueError

        # Remove elements and associated parameter values
        remove = spec["remove"].set[set_name]
        for element in remove:
            msg = f"{repr(element)} and associated parameter elements"

            if options.get("fast", False):
                log.info(f"  Skip removing {msg} (fast=True)")
                continue

            log.info(f"  Remove {msg}")
            strip_par_data(scenario, set_name, element, dry_run=dry_run, dump=dump)

        # Add elements
        add = [] if dry_run else spec["add"].set[set_name]
        for element in add:
            scenario.add_set(
                set_name,
                element.id if isinstance(element, Code) else element,
            )

        if len(add):
            log.info(f"  Add {len(add)} element(s)")
            log.debug("  " + ellipsize(add))

        log.info("  ---")

    N_removed = sum(len(d) for d in dump.values())
    log.info(f"{N_removed} parameter elements removed")

    # Add units to the Platform before adding data
    for unit in spec["add"].set["unit"]:
        unit = unit if isinstance(unit, Code) else Code(id=unit, name=unit)
        log.info(f"Add unit {repr(unit)}")
        scenario.platform.add_unit(unit.id, comment=str(unit.name))

    # Add data
    if callable(data):
        result = data(scenario, dry_run=dry_run)
        if result:
            # `data` function returned some data; use add_par_data()
            add_par_data(scenario, result, dry_run=dry_run)

    # Finalize
    log.info("Commit results.")
    maybe_commit(
        scenario,
        condition=not dry_run,
        message=options.get("message", f"{__name__}.apply_spec()"),
    )