-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,143 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,9 @@ Cargo.lock | |
|
||
# These are backup files generated by rustfmt | ||
**/*.rs.bk | ||
|
||
|
||
# Added by cargo | ||
|
||
/target | ||
/Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[package] | ||
name = "tree_traversal" | ||
description = "Find best leaf node in a tree" | ||
repository = "https://github.com/lucidfrontier45/tree_traversal" | ||
keywords = ["combinatorial", "optimization", "tree", "graph"] | ||
license-file = "LICENSE" | ||
readme = "README.md" | ||
categories = ["algorithms"] | ||
version = "0.1.0" | ||
edition = "2021" | ||
authors = ["Du Shiqiao <[email protected]>"] | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
num-traits = "0.2.15" | ||
|
||
[lib] | ||
name = "tree_traversal" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,104 @@ | ||
# tree_traversal | ||
A Rust library for finding the optimal leaf node in a tree structure. | ||
This crate implements several tree traversal algorithms to find the best (the lowest cost) leaf node in a tree. | ||
|
||
# Algorithms | ||
|
||
- Breadth First Search | ||
- Depth First Search | ||
- Beam Search | ||
- Branch and Bound Search | ||
- Greedy Search | ||
|
||
# Using this crate | ||
|
||
```bash | ||
cargo add tree_traversal | ||
``` | ||
|
||
# Example | ||
|
||
```rust | ||
use tree_traversal::bbs::bbs; | ||
|
||
type Node = Vec<bool>; | ||
|
||
fn main() { | ||
let weights = [4, 2, 6, 3, 4]; | ||
let profits = [100, 20, 2, 5, 10]; | ||
let capacity = 8 as u32; | ||
let total_items = weights.len(); | ||
|
||
let successor_fn = |n: &Node| { | ||
if n.len() == total_items { | ||
return vec![]; | ||
} | ||
|
||
let total_weight: u32 = n | ||
.iter() | ||
.copied() | ||
.enumerate() | ||
.map(|(i, b)| { | ||
if b { | ||
return weights[i]; | ||
} else { | ||
return 0; | ||
} | ||
}) | ||
.sum(); | ||
|
||
let mut childrean = vec![]; | ||
|
||
let next_idx = n.len(); | ||
if capacity >= total_weight + weights[next_idx] { | ||
let mut c1 = n.clone(); | ||
c1.push(true); | ||
childrean.push(c1); | ||
} | ||
|
||
let mut c2 = n.clone(); | ||
c2.push(false); | ||
childrean.push(c2); | ||
|
||
childrean | ||
}; | ||
|
||
let total_profit = |n: &Node| { | ||
let s: u32 = n | ||
.iter() | ||
.copied() | ||
.enumerate() | ||
.map(|(i, b)| { | ||
if b { | ||
return profits[i]; | ||
} else { | ||
return 0; | ||
} | ||
}) | ||
.sum(); | ||
s | ||
}; | ||
|
||
// tree traversal assumes a minimization problem | ||
// if you want to solve maximization problem, subtract your actual score from the MAX value | ||
let lower_bound_fn = |n: &Node| { | ||
let current_profit = total_profit(n); | ||
let max_remained_profit: u32 = profits[n.len()..].into_iter().sum(); | ||
u32::MAX - (current_profit + max_remained_profit) | ||
}; | ||
|
||
let cost_fn = |n: &Node| u32::MAX - total_profit(n); | ||
|
||
let leaf_check_fn = |n: &Node| n.len() == total_items; | ||
|
||
let (cost, best_node) = | ||
bbs(vec![], successor_fn, lower_bound_fn, cost_fn, leaf_check_fn).unwrap(); | ||
let cost = u32::MAX - cost; | ||
|
||
dbg!((best_node, cost)); | ||
} | ||
``` | ||
|
||
# Note | ||
|
||
The API is derived from the great [pathfinding](https://docs.rs/pathfinding/latest/pathfinding/index.html) crate. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
use tree_traversal::bbs::bbs; | ||
|
||
type Node = Vec<bool>; | ||
fn main() { | ||
let weights = [4, 2, 6, 3, 4]; | ||
let profits = [100, 20, 2, 5, 10]; | ||
let capacity = 8 as u32; | ||
let total_items = weights.len(); | ||
|
||
let successor_fn = |n: &Node| { | ||
if n.len() == total_items { | ||
return vec![]; | ||
} | ||
|
||
let total_weight: u32 = n | ||
.iter() | ||
.copied() | ||
.enumerate() | ||
.map(|(i, b)| { | ||
if b { | ||
return weights[i]; | ||
} else { | ||
return 0; | ||
} | ||
}) | ||
.sum(); | ||
|
||
let mut childrean = vec![]; | ||
|
||
let next_idx = n.len(); | ||
if capacity >= total_weight + weights[next_idx] { | ||
let mut c1 = n.clone(); | ||
c1.push(true); | ||
childrean.push(c1); | ||
} | ||
|
||
let mut c2 = n.clone(); | ||
c2.push(false); | ||
childrean.push(c2); | ||
|
||
childrean | ||
}; | ||
|
||
let total_profit = |n: &Node| { | ||
let s: u32 = n | ||
.iter() | ||
.copied() | ||
.enumerate() | ||
.map(|(i, b)| { | ||
if b { | ||
return profits[i]; | ||
} else { | ||
return 0; | ||
} | ||
}) | ||
.sum(); | ||
s | ||
}; | ||
|
||
let lower_bound_fn = |n: &Node| { | ||
let current_profit = total_profit(n); | ||
let max_remained_profit: u32 = profits[n.len()..].into_iter().sum(); | ||
u32::MAX - (current_profit + max_remained_profit) | ||
}; | ||
|
||
let cost_fn = |n: &Node| u32::MAX - total_profit(n); | ||
|
||
let leaf_check_fn = |n: &Node| n.len() == total_items; | ||
|
||
let (cost, best_node) = | ||
bbs(vec![], successor_fn, lower_bound_fn, cost_fn, leaf_check_fn).unwrap(); | ||
let cost = u32::MAX - cost; | ||
|
||
dbg!((best_node, cost)); | ||
} |
Oops, something went wrong.