mirror of
https://github.com/L-yang-yang/cugenopt.git
synced 2026-04-25 12:16:21 +02:00
109 lines
4 KiB
Python
109 lines
4 KiB
Python
|
|
"""
|
||
|
|
TSP-specific custom operators.
|
||
|
|
|
||
|
|
These operators exploit TSP structure (distance matrix, route continuity)
|
||
|
|
to perform more effective local search than generic permutation operators.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from cugenopt.operators import CustomOperator
|
||
|
|
|
||
|
|
_TSP_2OPT_DELTA = CustomOperator(
|
||
|
|
name="tsp_2opt_delta",
|
||
|
|
code=r"""
|
||
|
|
int row = 0;
|
||
|
|
int sz = sol.dim2_sizes[row];
|
||
|
|
if (sz < 4) return false;
|
||
|
|
int n = prob->_n;
|
||
|
|
const float* dist = prob->d_dist;
|
||
|
|
int i = rand_int(rng, sz);
|
||
|
|
int j = rand_int(rng, sz - 2);
|
||
|
|
if (j >= i) j += 2; else if (j == i - 1) j = (i + sz - 1) % sz;
|
||
|
|
if (i > j) { int t = i; i = j; j = t; }
|
||
|
|
if (j - i < 2 || j - i >= sz - 1) return false;
|
||
|
|
int a = sol.data[row][i], b = sol.data[row][(i+1) % sz];
|
||
|
|
int c = sol.data[row][j], d = sol.data[row][(j+1) % sz];
|
||
|
|
float old_cost = dist[a * n + b] + dist[c * n + d];
|
||
|
|
float new_cost = dist[a * n + c] + dist[b * n + d];
|
||
|
|
if (new_cost >= old_cost) return false;
|
||
|
|
ops::perm_reverse(sol.data[row], i + 1, j);
|
||
|
|
return true;
|
||
|
|
""",
|
||
|
|
encoding="permutation",
|
||
|
|
initial_weight=1.5,
|
||
|
|
)
|
||
|
|
|
||
|
|
_TSP_OR_OPT_DELTA = CustomOperator(
|
||
|
|
name="tsp_or_opt_delta",
|
||
|
|
code=r"""
|
||
|
|
int row = 0;
|
||
|
|
int sz = sol.dim2_sizes[row];
|
||
|
|
if (sz < 5) return false;
|
||
|
|
int n = prob->_n;
|
||
|
|
const float* dist = prob->d_dist;
|
||
|
|
int seg_len = 1 + rand_int(rng, 3);
|
||
|
|
if (seg_len >= sz - 1) return false;
|
||
|
|
int from_pos = rand_int(rng, sz - seg_len);
|
||
|
|
int prev = sol.data[row][(from_pos + sz - 1) % sz];
|
||
|
|
int seg_start = sol.data[row][from_pos];
|
||
|
|
int seg_end = sol.data[row][from_pos + seg_len - 1];
|
||
|
|
int next = sol.data[row][(from_pos + seg_len) % sz];
|
||
|
|
float remove_cost = dist[prev * n + seg_start]
|
||
|
|
+ dist[seg_end * n + next]
|
||
|
|
- dist[prev * n + next];
|
||
|
|
int best_to = -1;
|
||
|
|
float best_delta = 0.0f;
|
||
|
|
for (int t = 0; t < 8; t++) {
|
||
|
|
int to = rand_int(rng, sz - seg_len);
|
||
|
|
if (to >= from_pos && to < from_pos + seg_len) continue;
|
||
|
|
int tp = sol.data[row][to];
|
||
|
|
int tn = sol.data[row][(to + 1) % sz];
|
||
|
|
float insert_cost = dist[tp * n + seg_start]
|
||
|
|
+ dist[seg_end * n + tn]
|
||
|
|
- dist[tp * n + tn];
|
||
|
|
float delta = insert_cost - remove_cost;
|
||
|
|
if (delta < best_delta) { best_delta = delta; best_to = to; }
|
||
|
|
}
|
||
|
|
if (best_to < 0) return false;
|
||
|
|
ops::perm_or_opt(sol.data[row], sz, from_pos, best_to, seg_len);
|
||
|
|
return true;
|
||
|
|
""",
|
||
|
|
encoding="permutation",
|
||
|
|
initial_weight=1.0,
|
||
|
|
)
|
||
|
|
|
||
|
|
_TSP_NODE_INSERT_DELTA = CustomOperator(
|
||
|
|
name="tsp_node_insert_delta",
|
||
|
|
code=r"""
|
||
|
|
int row = 0;
|
||
|
|
int sz = sol.dim2_sizes[row];
|
||
|
|
if (sz < 4) return false;
|
||
|
|
int n = prob->_n;
|
||
|
|
const float* dist = prob->d_dist;
|
||
|
|
int from_pos = rand_int(rng, sz);
|
||
|
|
int node = sol.data[row][from_pos];
|
||
|
|
int prev = sol.data[row][(from_pos + sz - 1) % sz];
|
||
|
|
int next = sol.data[row][(from_pos + 1) % sz];
|
||
|
|
float remove_save = dist[prev * n + node] + dist[node * n + next]
|
||
|
|
- dist[prev * n + next];
|
||
|
|
int best_to = -1;
|
||
|
|
float best_delta = 0.0f;
|
||
|
|
for (int t = 0; t < 8; t++) {
|
||
|
|
int to = rand_int(rng, sz - 1);
|
||
|
|
if (to >= from_pos) to++;
|
||
|
|
int tp = sol.data[row][to];
|
||
|
|
int tn = sol.data[row][(to + 1) % sz];
|
||
|
|
float insert_cost = dist[tp * n + node] + dist[node * n + tn]
|
||
|
|
- dist[tp * n + tn];
|
||
|
|
float delta = insert_cost - remove_save;
|
||
|
|
if (delta < best_delta) { best_delta = delta; best_to = to; }
|
||
|
|
}
|
||
|
|
if (best_to < 0) return false;
|
||
|
|
ops::perm_insert(sol.data[row], from_pos, best_to, sz);
|
||
|
|
return true;
|
||
|
|
""",
|
||
|
|
encoding="permutation",
|
||
|
|
initial_weight=1.0,
|
||
|
|
)
|
||
|
|
|
||
|
|
tsp_ops = [_TSP_2OPT_DELTA, _TSP_OR_OPT_DELTA, _TSP_NODE_INSERT_DELTA]
|