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.