Coverage for moptipyapps / binpacking2d / experiment.py: 50%
46 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-11 04:40 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-11 04:40 +0000
1"""An example experiment for bin packing."""
3import argparse
4from typing import Callable, Final, cast
6from moptipy.algorithms.so.ffa.fea1plus1 import FEA1plus1
7from moptipy.algorithms.so.rls import RLS
8from moptipy.api.encoding import Encoding
9from moptipy.api.execution import Execution
10from moptipy.api.experiment import run_experiment
11from moptipy.api.objective import Objective
12from moptipy.operators.signed_permutations.op0_shuffle_and_flip import (
13 Op0ShuffleAndFlip,
14)
15from moptipy.operators.signed_permutations.op1_swap_2_or_flip import (
16 Op1Swap2OrFlip,
17)
18from moptipy.spaces.signed_permutations import SignedPermutations
19from pycommons.io.path import Path
21from moptipyapps.binpacking2d.encodings.ibl_encoding_1 import (
22 ImprovedBottomLeftEncoding1,
23)
24from moptipyapps.binpacking2d.instance import Instance
25from moptipyapps.binpacking2d.packing_result import DEFAULT_OBJECTIVES
26from moptipyapps.binpacking2d.packing_space import PackingSpace
27from moptipyapps.utils.shared import moptipyapps_argparser
29#: the maximum number of FEs
30MAX_FES: Final[int] = 1_000_000
33def base_setup(instance: Instance,
34 encoding: Callable[[Instance], Encoding],
35 objective: Callable[[Instance], Objective]) \
36 -> tuple[SignedPermutations, Execution]:
37 """
38 Create the basic setup.
40 :param instance: the instance to use
41 :param encoding: the encoding function
42 :param objective: the objective function
43 :return: the search space and the basic execution
44 """
45 space: Final[SignedPermutations] = SignedPermutations(
46 instance.get_standard_item_sequence())
48 return (space, Execution().set_max_fes(MAX_FES).set_log_improvements(True)
49 .set_objective(objective(instance))
50 .set_encoding(encoding(instance))
51 .set_search_space(space)
52 .set_solution_space(PackingSpace(instance)))
55def rls(instance: Instance,
56 encoding: Callable[[Instance], Encoding],
57 objective: Callable[[Instance], Objective]) -> Execution:
58 """
59 Create the RLS setup.
61 :param instance: the instance to use
62 :param encoding: the encoding function
63 :param objective: the objective function
64 :return: the RLS execution
65 """
66 space, execute = base_setup(instance, encoding, objective)
67 return execute.set_algorithm(
68 RLS(Op0ShuffleAndFlip(space), Op1Swap2OrFlip()))
71def fea(instance: Instance,
72 encoding: Callable[[Instance], Encoding],
73 objective: Callable[[Instance], Objective]) -> Execution:
74 """
75 Create the FEA setup.
77 :param instance: the instance to use
78 :param encoding: the encoding function
79 :param objective: the objective function
80 :return: the RLS execution
81 """
82 space, execute = base_setup(instance, encoding, objective)
83 return execute.set_algorithm(
84 FEA1plus1(Op0ShuffleAndFlip(space), Op1Swap2OrFlip()))
87def run(base_dir: str, n_runs: int = 23) -> None:
88 """
89 Run the experiment.
91 :param base_dir: the base directory
92 :param n_runs: the number of runs, by default `23`
93 """
94 use_dir: Final[Path] = Path(base_dir)
95 use_dir.ensure_dir_exists()
97 encodings: Final[tuple[Callable[[Instance], Encoding], ...]] = (
98 ImprovedBottomLeftEncoding1,
99 )
100 instances: list[str] = [
101 inst for inst in Instance.list_resources()
102 if inst.startswith(("b", "a"))]
103 inst_creators: list[Callable[[], Instance]] = [cast(
104 "Callable[[], Instance]", lambda __s=sss: Instance.from_resource(__s))
105 for sss in instances]
106 namer: Final[Instance] = Instance.from_resource(instances[0])
108 for objective in DEFAULT_OBJECTIVES:
109 objective_dir: Path = use_dir.resolve_inside(str(objective(namer)))
110 objective_dir.ensure_dir_exists()
111 for encoding in encodings:
112 encoding_dir: Path = objective_dir.resolve_inside(
113 str(encoding(namer)))
114 encoding_dir.ensure_dir_exists()
115 run_experiment(
116 base_dir=encoding_dir,
117 instances=inst_creators,
118 setups=[
119 cast("Callable",
120 lambda ins, _e=encoding, _o=objective: rls(
121 ins, _e, _o)),
122 cast("Callable",
123 lambda ins, _e=encoding, _o=objective: fea(
124 ins, _e, _o))],
125 n_runs=n_runs,
126 perform_warmup=True,
127 perform_pre_warmup=True)
130# Run the experiment from the command line
131if __name__ == "__main__":
132 parser: Final[argparse.ArgumentParser] = moptipyapps_argparser(
133 __file__, "2D Bin Packing", "Run the 2D Bin Packing experiment.")
134 parser.add_argument(
135 "dest", help="the directory to store the experimental results under",
136 type=Path, nargs="?", default="./results/")
137 args: Final[argparse.Namespace] = parser.parse_args()
138 run(args.dest)