mirror of
https://github.com/tig-pool-nk/tig-monorepo.git
synced 2026-02-21 15:17:22 +08:00
This commit is contained in:
parent
78cf8f0255
commit
7e921ae4ba
@ -195,12 +195,128 @@ impl SubInstance {
|
||||
|
||||
// Step 1: Initial solution obtained by greedily selecting items based on value-weight ratio
|
||||
let mut selected_items = Vec::with_capacity(difficulty.num_items);
|
||||
let mut unselected_items = Vec::with_capacity(difficulty.num_items);
|
||||
let mut total_weight = 0;
|
||||
let mut total_value = 0;
|
||||
let mut is_selected = vec![false; difficulty.num_items];
|
||||
|
||||
for &(item, _) in &item_values {
|
||||
if total_weight + weights[item] <= max_weight {
|
||||
total_weight += weights[item];
|
||||
total_value += values[item] as i32;
|
||||
|
||||
for &prev_item in &selected_items {
|
||||
total_value += interaction_values[item][prev_item];
|
||||
}
|
||||
selected_items.push(item);
|
||||
is_selected[item] = true;
|
||||
} else {
|
||||
unselected_items.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Improvement of solution with Local Search and Tabu-List
|
||||
// Precompute sum of interaction values with each selected item for all items
|
||||
let mut interaction_sum_list = vec![0; difficulty.num_items];
|
||||
for x in 0..difficulty.num_items {
|
||||
interaction_sum_list[x] = values[x] as i32;
|
||||
for &item in &selected_items {
|
||||
interaction_sum_list[x] += interaction_values[x][item];
|
||||
}
|
||||
}
|
||||
|
||||
let mut min_selected_item_values = i32::MAX;
|
||||
for x in 0..difficulty.num_items {
|
||||
if is_selected[x] {
|
||||
min_selected_item_values = min_selected_item_values.min(interaction_sum_list[x]);
|
||||
}
|
||||
}
|
||||
|
||||
// Optimized local search with tabu list
|
||||
let max_iterations = 100;
|
||||
let mut tabu_list = vec![0; difficulty.num_items];
|
||||
|
||||
for _ in 0..max_iterations {
|
||||
let mut best_improvement = 0;
|
||||
let mut best_swap = None;
|
||||
|
||||
for i in 0..unselected_items.len() {
|
||||
let new_item = unselected_items[i];
|
||||
if tabu_list[new_item] > 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let new_item_values_sum = interaction_sum_list[new_item];
|
||||
if new_item_values_sum < best_improvement + min_selected_item_values {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute minimal weight of remove_item required to put new_item
|
||||
let min_weight =
|
||||
weights[new_item] as i32 - (max_weight as i32 - total_weight as i32);
|
||||
for j in 0..selected_items.len() {
|
||||
let remove_item = selected_items[j];
|
||||
if tabu_list[remove_item] > 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't check the weight if there is enough remaining capacity
|
||||
if min_weight > 0 {
|
||||
// Skip a remove_item if the remaining capacity after removal is insufficient to push a new_item
|
||||
let removed_item_weight = weights[remove_item] as i32;
|
||||
if removed_item_weight < min_weight {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let remove_item_values_sum = interaction_sum_list[remove_item];
|
||||
let value_diff = new_item_values_sum
|
||||
- remove_item_values_sum
|
||||
- interaction_values[new_item][remove_item];
|
||||
|
||||
if value_diff > best_improvement {
|
||||
best_improvement = value_diff;
|
||||
best_swap = Some((i, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((unselected_index, selected_index)) = best_swap {
|
||||
let new_item = unselected_items[unselected_index];
|
||||
let remove_item = selected_items[selected_index];
|
||||
|
||||
selected_items.swap_remove(selected_index);
|
||||
unselected_items.swap_remove(unselected_index);
|
||||
selected_items.push(new_item);
|
||||
unselected_items.push(remove_item);
|
||||
|
||||
is_selected[new_item] = true;
|
||||
is_selected[remove_item] = false;
|
||||
|
||||
total_value += best_improvement;
|
||||
total_weight = total_weight + weights[new_item] - weights[remove_item];
|
||||
|
||||
// Update sum of interaction values after swapping items
|
||||
min_selected_item_values = i32::MAX;
|
||||
for x in 0..difficulty.num_items {
|
||||
interaction_sum_list[x] +=
|
||||
interaction_values[x][new_item] - interaction_values[x][remove_item];
|
||||
if is_selected[x] {
|
||||
min_selected_item_values =
|
||||
min_selected_item_values.min(interaction_sum_list[x]);
|
||||
}
|
||||
}
|
||||
|
||||
// Update tabu list
|
||||
tabu_list[new_item] = 3;
|
||||
tabu_list[remove_item] = 3;
|
||||
} else {
|
||||
break; // No improvement found, terminate local search
|
||||
}
|
||||
|
||||
// Decrease tabu counters
|
||||
for t in tabu_list.iter_mut() {
|
||||
*t = if *t > 0 { *t - 1 } else { 0 };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user