Skip to content

Commit

Permalink
Merge branch 'release/0.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
lucidfrontier45 committed Sep 7, 2022
2 parents 55562b2 + 488d160 commit 4fad4e3
Show file tree
Hide file tree
Showing 10 changed files with 1,143 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk


# Added by cargo

/target
/Cargo.lock
19 changes: 19 additions & 0 deletions Cargo.toml
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"
102 changes: 102 additions & 0 deletions README.md
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.
75 changes: 75 additions & 0 deletions examples/bbs_knapsack_problem.rs
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));
}
Loading

0 comments on commit 4fad4e3

Please sign in to comment.