From 4e5df61c75209658e23a02f8abe40db82e690ffc Mon Sep 17 00:00:00 2001 From: FiveMovesAhead Date: Mon, 1 Dec 2025 15:23:26 +0000 Subject: [PATCH] Submitted knapsack/kp_heuristics --- .../src/knapsack/kp_heuristics/README.md | 23 +++ .../src/knapsack/kp_heuristics/mod.rs | 160 ++++++++++++++++++ tig-algorithms/src/knapsack/mod.rs | 3 +- 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 tig-algorithms/src/knapsack/kp_heuristics/README.md create mode 100644 tig-algorithms/src/knapsack/kp_heuristics/mod.rs diff --git a/tig-algorithms/src/knapsack/kp_heuristics/README.md b/tig-algorithms/src/knapsack/kp_heuristics/README.md new file mode 100644 index 00000000..ec29d8d7 --- /dev/null +++ b/tig-algorithms/src/knapsack/kp_heuristics/README.md @@ -0,0 +1,23 @@ +# TIG Code Submission + +## Submission Details + +* **Challenge Name:** knapsack +* **Algorithm Name:** kp_heuristics +* **Copyright:** 2024 CodeAlchemist +* **Identity of Submitter:** CodeAlchemist +* **Identity of Creator of Algorithmic Method:** null +* **Unique Algorithm Identifier (UAI):** null + +## License + +The files in this folder are under the following licenses: +* TIG Benchmarker Outbound License +* TIG Commercial License +* TIG Inbound Game License +* TIG Innovator Outbound Game License +* TIG Open Data License +* TIG THV Game License + +Copies of the licenses can be obtained at: +https://github.com/tig-foundation/tig-monorepo/tree/main/docs/licenses \ No newline at end of file diff --git a/tig-algorithms/src/knapsack/kp_heuristics/mod.rs b/tig-algorithms/src/knapsack/kp_heuristics/mod.rs new file mode 100644 index 00000000..03fdbd02 --- /dev/null +++ b/tig-algorithms/src/knapsack/kp_heuristics/mod.rs @@ -0,0 +1,160 @@ +use anyhow::{anyhow, Result}; +use serde_json::{Map, Value}; +use tig_challenges::knapsack::*; + + +pub fn solve_challenge( + challenge: &Challenge, + save_solution: &dyn Fn(&Solution) -> Result<()>, + hyperparameters: &Option>, +) -> Result<()> { + Err(anyhow!("This algorithm is no longer compatible.")) +} + +// Old code that is no longer compatible +#[cfg(none)] +mod dead_code { + use tig_challenges::knapsack::*; + use rand::{rngs::SmallRng, Rng, SeedableRng}; + + fn calculate_value_change( + current_solution: &[usize], + item: usize, + values: &[u32], + interaction_values: &[Vec] + ) -> i32 { + let mut value_change = values[item] as i32; + + for &other_item in current_solution { + value_change += interaction_values[item][other_item]; + } + + value_change + } + + + pub fn solve_challenge(challenge: &Challenge) -> anyhow::Result> { + let mut solution = Solution { + sub_solutions: Vec::new(), + }; + for sub_instance in &challenge.sub_instances { + match solve_sub_instance(sub_instance)? { + Some(sub_solution) => solution.sub_solutions.push(sub_solution), + None => return Ok(None), + } + } + Ok(Some(solution)) + } + + pub fn solve_sub_instance(challenge: &SubInstance) -> anyhow::Result> { + { + let coef = vec![7.685029664028169e-08, -0.00026933405380081394, 0.39570553839776795, 4.133197036353228, 8025.3579356210785]; + + let mut lim = 0.0; + let mut val = 1.0; + for i in (0..coef.len()).rev(){ + lim += coef[i] * val; + val *= challenge.num_items as f32; + } + + lim = lim * (1.0 as f32 + (challenge.difficulty.better_than_baseline as f32)/1000.0); + + if challenge.baseline_value as f32 > lim { + return Ok(None); + } + } + + let mut current_solution = greedy_initial_solution(challenge); + let mut current_value = calculate_total_value(¤t_solution, &challenge.values, &challenge.interaction_values); + let mut current_weight: u32 = current_solution.iter().map(|&i| challenge.weights[i]).sum(); + let mut best_value = current_value; + let mut rng = SmallRng::seed_from_u64(u64::from_le_bytes(challenge.seed[..8].try_into().unwrap()) as u64); + + let initial_temperature = 500.0; + let cooling_rate = 0.985; + let mut temperature = initial_temperature; + + while temperature > 1.0 { + for i in 0..challenge.num_items { + let item_pos = current_solution.binary_search(&i); + + let (new_solution, new_weight, new_value) = match item_pos { + Ok(pos) => { + // Remove item + let mut new_sol = current_solution.clone(); + let new_weight = current_weight - challenge.weights[i]; + new_sol.remove(pos); + let new_value = current_value as i32 - calculate_value_change(¤t_solution, i, &challenge.values, &challenge.interaction_values); + (new_sol, new_weight, new_value) + }, + Err(pos) => { + // Add item + let new_weight = current_weight + challenge.weights[i]; + if new_weight <= challenge.max_weight { + let mut new_sol = current_solution.clone(); + new_sol.insert(pos, i); + + let new_value = current_value as i32 + calculate_value_change(¤t_solution, i, &challenge.values, &challenge.interaction_values); + (new_sol, new_weight, new_value) + } else { + continue; + } + } + }; + + let delta = new_value - current_value as i32; + if delta > 0 || rng.gen::() < (delta as f64 / temperature).exp() { + current_solution = new_solution; + current_value = new_value as u32; + current_weight = new_weight; + + if current_value > best_value && current_weight <= challenge.max_weight { + best_value = current_value; + } + } + + if current_value >= challenge.baseline_value && current_weight <= challenge.max_weight { + return Ok(Some(SubSolution { items: current_solution })); + } + } + + temperature *= cooling_rate; + } + + Ok(None) + } + + fn greedy_initial_solution(challenge: &SubInstance) -> Vec { + let n = challenge.weights.len(); + let mut solution = Vec::new(); + let mut current_weight = 0; + + let mut items: Vec<(usize, f64)> = (0..n) + .map(|i| { + let total_value = challenge.values[i] as i32 + challenge.interaction_values[i].iter().sum::(); + let ratio = total_value as f64 / challenge.weights[i] as f64; + (i, ratio) + }) + .collect(); + + items.sort_unstable_by(|a, b| b.1.partial_cmp(&a.1).unwrap()); + + for (i, _) in items { + if current_weight + challenge.weights[i] <= challenge.max_weight { + solution.push(i); + current_weight += challenge.weights[i]; + } + } + + solution.sort_unstable(); + solution + } + + + + // Important! Do not include any tests in this file, it will result in your submission being rejected +} + +pub fn help() { + println!("No help information available."); +} diff --git a/tig-algorithms/src/knapsack/mod.rs b/tig-algorithms/src/knapsack/mod.rs index 33ddf59d..32af8396 100644 --- a/tig-algorithms/src/knapsack/mod.rs +++ b/tig-algorithms/src/knapsack/mod.rs @@ -120,7 +120,8 @@ // c003_a061 -// c003_a062 +pub mod kp_heuristics; +pub use kp_heuristics as c003_a062; // c003_a063