OSDN Git Service

Correct my name in all copyrights (Dederichs) and added Janos as Copyright to all...
[bin-packing-3d/or_project_inform.git] / src / inform-runner / run_ep_heuristic.py
1 # -*- coding: utf-8 -*-
2 """Module for running the EP heuristic from the runner directory."""
3
4 #  Copyright (c) 2020.  Yordan Manolov <yordan DOT manolov AT rwth DASH aachen DOT de >
5 #  Copyright (c) 2020.  Moritz Dederichs
6
7 import argparse
8 import logging
9 import time
10 from statistics import mean
11 from typing import List
12 import pprint
13 import os
14
15 from inform_or_ep_objects.box import Box
16 from inform_or_models.extreme_points_heuristic import extreme_points, \
17     print_instruction_description_to_file
18 from inform_or_parser import parse_csv_extreme_points
19
20 logging.basicConfig(filename="../../Latex/presentation/benchmarks/ep/ep_debug.log",
21                     filemode="a",
22                     format="%(asctime)s %(message)s",
23                     level="DEBUG")
24
25
26 def run_experiment(arguments: argparse.Namespace):
27     """ This function starts the current experiment using the extreme points heuristic with the given arguments.
28
29     Parameters
30     ----------
31     arguments: argparse.Namespace
32         The parsed commandline arguments given by script start.
33
34     Returns
35     -------
36     """
37     instruction = os.path.join(arguments.output, 'instructions_ep.txt')
38     print_instruction_description_to_file(instruction)
39     orders = parse_csv_extreme_points.parse_file_as_objects(arguments.input)
40     order_from = arguments.first
41     order_until = arguments.last
42     if isinstance(order_until, int):
43         order_until += 1
44     orders = orders[order_from:order_until]
45     processed_orders = list()
46     start_all_orders = time.perf_counter()
47
48     for order in orders:
49         start_current_order = time.perf_counter()
50         result = extreme_points(order, instruction, arguments)
51         processed_orders.append(result)
52         end_current_order = time.perf_counter()
53         time_current_order = end_current_order - start_current_order
54         stat_me("Order no. " + order.identifier,
55                 1,
56                 time_current_order,
57                 result)
58
59     box_list = [box.standard_size for order in processed_orders for box in order]
60     with open(os.path.join(arguments.output, 'complete_ep_list.txt'), 'w') as file:
61         pprint.pprint(box_list, file)
62
63     end_all_orders = time.perf_counter()
64     time_all_orders = end_all_orders - start_all_orders
65     stat_me("Category from " + str(orders[0].identifier) +
66             " to " + str(orders[-1].identifier),
67             len(orders),
68             time_all_orders,
69             processed_orders)
70
71
72 def __parse_arguments() -> argparse.Namespace:
73     """ Function to process the given commandline arguments
74
75     Returns
76     -------
77     argparse.Namespace:
78         An object containing the values of each commandline argument.
79     """
80     parser = argparse.ArgumentParser()
81
82     # Mandatory Arguments
83     parser.add_argument('input', help='path to the input file to be read',
84                         type=str)
85     parser.add_argument('output',
86                         help="path to the output directory to store all packing instructions.",
87                         type=str)
88
89     # Optional Arguments
90     parser.add_argument('-m', '--merit_function',
91                         help="merit function to use for EP-BFD.",
92                         choices=['fv', 'mp', 'lev', 'rs'],
93                         default=None)
94     parser.add_argument('-s', '--sorting',
95                         help="criterion for sorting the items.",
96                         choices=["area", 'area_height', "height",
97                                  'height_area', 'height_volume', 'volume',
98                                  'volume_height'],
99                         default='height_area')
100     parser.add_argument('-f', '--first',
101                         help='order ID of the first order in the input file to be packed. If none is given the packing will start with the first order in the input file',
102                         type=int, default=None)
103     parser.add_argument('-l', '--last',
104                         help="order ID of the last order in the input file to be packed. If none is given the packing will end with the last order in the input file",
105                         type=int, default=None)
106     return parser.parse_args()
107
108
109 def stat_me(descriptor: str,
110             length: int = 1,
111             elapsed_time: float = 0,
112             packing_result: List[Box] or List[List[Box]] = None):
113     """
114
115     Parameters
116     ----------
117     descriptor What kind of input is benchmarked, e.g. single order, category of orders etc
118     length The length of the input for which packing_result was computed
119     elapsed_time The time it took to produce packing_result
120     packing_result The output of the Extreme Points-based heuristic with input as described in descriptor
121
122     Returns
123     -------
124
125
126     """
127     if not isinstance(packing_result[0], Box):
128         packing_result_flattened = [x for y in packing_result for x in y]
129     else:
130         packing_result_flattened = packing_result
131     if "Category" in descriptor:
132         logging.debug("Details for %s : \n"
133                       "Total time (in seconds) : %s \n"
134                       "Number of boxes : %s \n"
135                       "Avg. number of boxes : %s \n"
136                       "Free volume (total) : %s \n"
137                       "Avg. free volume: %s percent",
138                       descriptor,
139                       elapsed_time,
140                       len(packing_result_flattened),
141                       divmod(len(packing_result_flattened),
142                              length)[0],
143                       sum([x.get_free_volume() for x in
144                            packing_result_flattened]),
145                       mean([x.get_free_volume_ratio() for x in
146                             packing_result_flattened])
147                       )
148
149
150 if __name__ == "__main__":
151     args = __parse_arguments()
152     run_experiment(args)