How to use ML4CO-Kit

Case-01: How to use ML4CO-Kit to generate a dataset

 1# We take the TSP as an example
 2
 3# Import the required classes.
 4>>> import numpy as np                  # Numpy
 5>>> from ml4co_kit import TSPWrapper    # The wrapper for TSP, used to manage data and parallel generation.
 6>>> from ml4co_kit import TSPGenerator  # The generator for TSP, used to generate a single instance.
 7>>> from ml4co_kit import TSP_TYPE      # The distribution types supported by the generator.
 8>>> from ml4co_kit import LKHSolver     # We choose LKHSolver to solve TSP instances
 9
10# Check which distributions are supported by the TSP types.
11>>> for type in TSP_TYPE:
12...     print(type)
13TSP_TYPE.UNIFORM
14TSP_TYPE.GAUSSIAN
15TSP_TYPE.CLUSTER
16
17# Set the generator parameters according to the requirements.
18>>> tsp_generator = TSPGenerator(
19...     distribution_type=TSP_TYPE.GAUSSIAN,   # Generate a TSP instance with a Gaussian distribution
20...     precision=np.float32,                  # Floating-point precision: 32-bit
21...     nodes_num=50,                          # Number of nodes in TSP instance
22...     gaussian_mean_x=0,                     # Mean of Gaussian for x coordinate
23...     gaussian_mean_y=0,                     # Mean of Gaussian for y coordinate
24...     gaussian_std=1,                        # Standard deviation of Gaussian
25... )
26
27# Set the LKH parameters.
28>>> tsp_solver = LKHSolver(
29...     lkh_scale=1e6,        # Scaling factor to convert floating-point numbers to integers
30...     lkh_max_trials=500,   # Maximum number of trials for the LKH algorithm
31...     lkh_path="LKH",       # Path to the LKH executable
32...     lkh_runs=1,           # Number of runs for the LKH algorithm
33...     lkh_seed=1234,        # Random seed for the LKH algorithm
34...     lkh_special=False,    # When set to True, disables 2-opt and 3-opt heuristics
35... )
36
37# Create the TSP wrapper
38>>> tsp_wrapper = TSPWrapper(precision=np.float32)
39
40# Use ``generate_w_to_txt`` to generate a dataset of TSP.
41>>> tsp_wrapper.generate_w_to_txt(
42...     file_path="tsp_gaussian_16ins.txt",  # Path to the output file where the generated TSP instances will be saved
43...     generator=tsp_generator,             # The TSP instance generator to use
44...     solver=tsp_solver,                   # The TSP solver to use
45...     num_samples=16,                      # Number of TSP instances to generate
46...     num_threads=4,                       # Number of CPU threads to use for parallelization; cannot both be non-1 with batch_size
47...     batch_size=1,                        # Batch size for parallel processing; cannot both be non-1 with num_threads
48...     write_per_iters=1,                   # Number of sub-generation steps after which data will be written to the file
49...     write_mode="a",                      # Write mode for the output file ("a" for append)
50...     show_time=True,                      # Whether to display the time taken for the generation process
51... )
52Generating TSP: 100%|..........| 4/4 [00:00<00:00, 12.79it/s]

Case-02: How to use ML4CO-Kit to load problems and solve them

 1# We take the MIS as an example
 2
 3# Import the required classes.
 4>>> import numpy as np                  # Numpy
 5>>> from ml4co_kit import MISWrapper    # The wrapper for MIS, used to manage data and parallel solving.
 6>>> from ml4co_kit import KaMISSolver   # We choose KaMISSolver to solve MIS instances
 7
 8# Set the KaMIS parameters.
 9>>> mis_solver = KaMISSolver(
10...     kamis_time_limit=10.0,          # The maximum solution time for a single problem
11...     kamis_weighted_scale=1e5,       # Weight scaling factor, used when nodes have weights.
12... )
13
14# Create the MIS wrapper
15>>> mis_wrapper = MISWrapper(precision=np.float32)
16
17# Load the problems to be solved.
18# You can use the corresponding loading function based on the file type,
19# such as ``from_txt`` for txt file and ``from_pickle`` for pickle file.
20>>> mis_wrapper.from_txt(
21...     file_path="test_dataset/mis/wrapper/mis_rb-small_uniform-weighted_4ins.txt",
22...     ref=True,          # TXT file contains labels. Set ``ref=True`` to set them as reference.
23...     overwrite=True,    # Whether to overwrite the data. If not, only update according to the file data.
24...     show_time=True     # Whether to display the time taken for the loading process
25... )
26Loading data from test_dataset/mis/wrapper/mis_rb-small_uniform-weighted_4ins.txt: 4it [00:00, 75.41it/s]
27
28# Use ``solve`` to call the KaMISSolver to perform the solution.
29>>> mis_wrapper.solve(
30...     solver=mis_solver,                   # The solver to use
31...     num_threads=2,                       # Number of CPU threads to use for parallelization; cannot both be non-1 with batch_size
32...     batch_size=1,                        # Batch size for parallel processing; cannot both be non-1 with num_threads
33...     show_time=True,                      # Whether to display the time taken for the generation process
34... )
35Solving MIS Using kamis: 100%|..........| 2/2 [00:21<00:00, 10.97s/it]
36Using Time: 21.947036743164062
37
38# Use ``evaluate_w_gap`` to obtain the evaluation results.
39# Evaluation Results: average solution value, average reference value, gap (%), gap std.
40>>> eval_result = mis_wrapper.evaluate_w_gap()
41>>> print(eval_result)
42(14.827162742614746, 15.18349838256836, 2.5054726600646973, 2.5342845916748047)

Case-03: How to use ML4CO-Kit to visualize the COPs

 1# We take the CVRP as an example
 2
 3# Import the required classes.
 4>>> import numpy as np                  # Numpy
 5>>> from ml4co_kit import CVRPTask      # CVRP Task.
 6>>> from ml4co_kit import CVRPWrapper   # The wrapper for CVRP, used to manage data.
 7
 8# Case-1: multiple task data are saved in ``txt``, ``pickle``, etc. single task data is saved in pickle.
 9>>> cvrp_wrapper = CVRPWrapper()
10>>> cvrp_wrapper.from_pickle("test_dataset/cvrp/wrapper/cvrp50_uniform_16ins.pkl")
11>>> cvrp_task = cvrp_wrapper.task_list[0]
12>>> print(cvrp_task)
13CVRPTask(2fb389cdafdb4e79a94572f01edf0b95)
14
15# Case-2: single task data is saved in pickle.
16>>> cvrp_task = CVRPTask()
17>>> cvrp_task.from_pickle("test_dataset/cvrp/task/cvrp50_uniform_task.pkl")
18>>> print(cvrp_task)
19CVRPTask(2fb389cdafdb4e79a94572f01edf0b95)
20
21# The loaded solution is usually a reference solution.
22# When drawing the image, it is the ``sol`` that is being drawn.
23# Therefore, it is necessary to assign ``ref_sol`` to ``sol``.
24>>> cvrp_task.sol = cvrp_task.ref_sol
25
26# Using ``render`` to get the visualization
27>>> cvrp_task.render(
28...     save_path="./docs/assets/cvrp_solution.png",  # Path to save the rendered image
29...     with_sol=True,                                # Whether to draw the solution tour
30...     figsize=(10, 10),                             # Size of the image (width and height)
31...     node_color="darkblue",                        # Color of the nodes
32...     edge_color="darkblue",                        # Color of the edges
33...     node_size=50                                  # Size of the nodes
34... )

Case-04: A simple ML4CO example

 1# We take the MCut as an example
 2
 3# Import the required classes.
 4>>> import numpy as np                   # Numpy
 5>>> from ml4co_kit import TASK_TYPE      # The task type.
 6>>> from ml4co_kit import MCutWrapper    # The wrapper for MCutWrapper, used to manage data.
 7>>> from ml4co_kit import GNN4COSolver   # GNN4COSolver.
 8>>> from ml4co_kit import RLSAOptimizer  # Using RLSA to perform local search.
 9>>> from ml4co_kit.extension.gnn4co import GNN4COModel, GNN4COEnv, GNNEncoder, GNN4COGreedyDecoder
10
11# Set the GNN4COModel parameters. ``weight_path``: Pretrain weight path.
12# If it is not available locally, it will be automatically downloaded from Hugging Face.
13>>> gnn4mcut_model = GNN4COModel(
14...     env=GNN4COEnv(
15...         task_type=TASK_TYPE.MCUT,    # Task type: MCut.
16...         wrapper=MCutWrapper(),       # The wrapper for MCutWrapper, used to manage data.
17...         mode="solve",                # Mode: solving mode.
18...         sparse_factor=1,             # Sparse factor: Controls the sparsity of the graph.
19...         device="cuda"                # Device: 'cuda' or 'cpu'
20...     ),
21...     encoder=GNNEncoder(
22...         task_type=TASK_TYPE.MCUT,    # Task type: MCut.
23...         sparse=True,                 # Graph data should set ``sparse`` to True.
24...         block_layers=[2,4,4,2]       # Block layers: the number of layers in each block of the encoder.
25...     ),
26...     decoder=GNN4COGreedyDecoder(sparse_factor=1),
27...     weight_path="weights/gnn4co_mcut_ba-large_sparse.pt"
28... )
29gnn4co/gnn4co_mcut_ba-large_sparse.pt: 100% ███████████████ 19.6M/19.6M [00:03<00:00, 6.18MB/s]
30
31# Set the RLSAOptimizer parameters.
32>>> mcut_optimizer = RLSAOptimizer(
33...     rlsa_kth_dim="both",          # Which dimension to consider for the k-th value calculation.
34...     rlsa_tau=0.01,                # The temperature parameter in the Simulated Annealing process.
35...     rlsa_d=2,                     # Control the step size of each update.
36...     rlsa_k=1000,                  # The number of samples used in the optimization process.
37...     rlsa_t=1000,                  # The number of iterations in the optimization process.
38...     rlsa_device="cuda",           # Device: 'cuda' or 'cpu'.
39...     rlsa_seed=1234                # The random seed for reproducibility.
40... )
41
42# Set the GNN4COSolver parameters.
43>>> mcut_solver_wo_opt = GNN4COSolver(
44...     model=gnn4mcut_model,         # GNN4CO model for MCut
45...     device="cuda",                # Device: 'cuda' or 'cpu'.
46...     optimizer=None                # The optimizer to perform local search.
47... )
48>>> mcut_solver_w_opt = GNN4COSolver(
49...     model=gnn4mcut_model,         # GNN4CO model for MCut
50...     device="cuda",                # Device: 'cuda' or 'cpu'.
51...     optimizer=mcut_optimizer      # The optimizer to perform local search.
52... )
53
54# Create the MCut wrapper
55>>> mcut_wrapper = MCutWrapper(precision=np.float32)
56
57# Load the problems to be solved.
58# You can use the corresponding loading function based on the file type,
59# such as ``from_txt`` for txt file and ``from_pickle`` for pickle file.
60>>> mcut_wrapper.from_txt(
61...     file_path="test_dataset/mcut/wrapper/mcut_ba-large_no-weighted_4ins.txt",
62...     ref=True,          # TXT file contains labels. Set ``ref=True`` to set them as reference.
63...     overwrite=True,    # Whether to overwrite the data. If not, only update according to the file data.
64...     show_time=True     # Whether to display the time taken for the loading process
65... )
66Loading data from test_dataset/mcut/wrapper/mcut_ba-large_no-weighted_4ins.txt: 4it [00:00, 16.35it/s]
67
68# Using ``solve`` to get the solution (without optimizer)
69>>> mcut_wrapper.solve(
70...     solver=mcut_solver_wo_opt,    # The solver to use
71...     num_threads=1,                # Number of CPU threads to use for parallelization; cannot both be non-1 with batch_size
72...     batch_size=1,                 # Batch size for parallel processing; cannot both be non-1 with num_threads
73...     show_time=True,               # Whether to display the time taken for the generation process
74... )
75Solving MCut Using greedy: 100%|██████████| 4/4 [00:00<00:00, 12.34it/s]
76Using Time: 0.3261079788208008
77
78# Use ``evaluate_w_gap`` to obtain the evaluation results.
79# Evaluation Results: average solution value, average reference value, gap (%), gap std.
80>>> eval_result = mcut_wrapper.evaluate_w_gap()
81>>> print(eval_result)
82(2647.25, 2726.5, 2.838811523236064, 0.7528157058230817)
83
84# Using ``solve`` to get the solution (with optimizer)
85>>> mcut_wrapper.solve(
86...     solver=mcut_solver_w_opt,     # The solver to use
87...     num_threads=1,                # Number of CPU threads to use for parallelization; cannot both be non-1 with batch_size
88...     batch_size=1,                 # Batch size for parallel processing; cannot both be non-1 with num_threads
89...     show_time=True,               # Whether to display the time taken for the generation process
90... )
91Solving MCut Using greedy: 100%|██████████| 4/4 [00:02<00:00,  1.46it/s]
92Using Time: 2.738525867462158
93
94# Use ``evaluate_w_gap`` to obtain the evaluation results.
95# Evaluation Results: average solution value, average reference value, gap (%), gap std.
96>>> eval_result = mcut_wrapper.evaluate_w_gap()
97>>> print(eval_result)
98(2693.0, 2726.5, 1.2373146256952277, 0.29320238806274546)

What’s Next

Please see API and Module for the API documentation.