Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Rust

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

env:
CARGO_TERM_COLOR: always

jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
toolchain: ["stable"]

steps:
- uses: actions/checkout@v4

- name: Install toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}

- name: Install 32bit target
run: rustup target add i686-unknown-linux-musl
- name: Install wasm target
run: rustup target add wasm32v1-none
- name: Install miri
run: rustup component add --toolchain nightly-x86_64-unknown-linux-gnu miri
- name: Install no-std-check
run: cargo install cargo-no-std-check

- name: Build
run: cargo build --verbose --features impl_all
- name: Build-32bit
run: cargo build --verbose --target i686-unknown-linux-musl
- name: Build-wasm
run: cargo build --verbose --no-default-features --target wasm32v1-none

- name: Test
run: cargo test --verbose --features impl_all
- name: Test-32bit
run: cargo test --verbose --target i686-unknown-linux-musl
- name: Check-wasm
run: cargo check --verbose --no-default-features --target wasm32v1-none

- name: Clippy
run: cargo clippy --features impl_all -- -D warnings --verbose

- name: Miri
run: cargo +nightly miri test --verbose

- name: NoStd
run: cargo +nightly no-std-check --no-default-features
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
[package]
name = "orx-priority-queue"
version = "1.7.0"
edition = "2021"
edition = "2024"
authors = ["orxfun <orx.ugur.arikan@gmail.com>"]
readme = "README.md"
description = "Priority queue traits and high performance d-ary heap implementations."
license = "MIT OR Apache-2.0"
repository = "https://github.com/orxfun/orx-priority-queue/"
Expand All @@ -13,9 +14,10 @@ categories = ["algorithms", "data-structures", "mathematics", "no-std"]
default = ["std"]
std = []
impl_priority_queue = ["priority-queue"]
impl_all = ["impl_priority_queue"]

[dependencies]
priority-queue = { version = "2.1", optional = true }
priority-queue = { version = "2.3", optional = true }


[[bench]]
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

Priority queue traits and high performance d-ary heap implementations.

> **no-std**: This crate supports **no-std**; however, *std* is added as a default feature. Please include with **no-default-features** for no-std use cases: `cargo add orx-priority-queue --no-default-features`.

## A. Priority Queue Traits

This crate aims to provide algorithms with the abstraction over priority queues. In order to achieve this, two traits are defined: **`PriorityQueue<N, K>`** and **`PriorityQueueDecKey<N, K>`**. The prior is a simple queue while the latter extends it by providing additional methods to change priorities of the items that already exist in the queue.
Expand Down Expand Up @@ -52,6 +54,7 @@ In addition, queue implementations are provided in this crate for the following
* `std::collections::BinaryHeap<(N, K)>` implements only `PriorityQueue<N, K>`,
* `priority_queue:PriorityQueue<N, K>` implements both `PriorityQueue<N, K>` and `PriorityQueueDecKey<N, K>`
* requires `--features impl_priority_queue`
* or `--features impl_all`

This allows to use all the queue implementations interchangeably and pick the one fitting best to the use case.

Expand Down
8 changes: 4 additions & 4 deletions benches/basic_queue.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use criterion::{
black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, BenchmarkId,
Criterion,
BenchmarkGroup, BenchmarkId, Criterion, black_box, criterion_group, criterion_main,
measurement::WallTime,
};
use orx_priority_queue::*;
use rand::prelude::*;
Expand All @@ -16,12 +16,12 @@ impl TestData {

let mut first_push = Vec::new();
for node in 0..n_first {
first_push.push((node, rng.gen()));
first_push.push((node, rng.random()));
}

let mut second_push = Vec::new();
for node in n_first..(n_first + n_second) {
second_push.push((node, rng.gen()));
second_push.push((node, rng.random()));
}

Self {
Expand Down
14 changes: 7 additions & 7 deletions benches/deckey_queue.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use criterion::{
black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, BenchmarkId,
Criterion,
BenchmarkGroup, BenchmarkId, Criterion, black_box, criterion_group, criterion_main,
measurement::WallTime,
};
use orx_priority_queue::*;
use rand::prelude::*;
Expand All @@ -17,19 +17,19 @@ impl TestData {

let mut push = Vec::new();
for node in 0..n_push {
push.push((node, rng.gen()));
push.push((node, rng.random()));
}

let mut first_deckey = Vec::new();
for _ in 0..n_deckey1 {
let node = rng.gen_range(0..n_push);
first_deckey.push((node, rng.gen()));
let node = rng.random_range(0..n_push);
first_deckey.push((node, rng.random()));
}

let mut second_deckey = Vec::new();
for _ in 0..n_deckey2 {
let node = rng.gen_range(0..n_push);
second_deckey.push((node, rng.gen()));
let node = rng.random_range(0..n_push);
second_deckey.push((node, rng.random()));
}

Self {
Expand Down
8 changes: 4 additions & 4 deletions benches/push_then_pop.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use criterion::{
black_box, criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, BenchmarkId,
Criterion,
BenchmarkGroup, BenchmarkId, Criterion, black_box, criterion_group, criterion_main,
measurement::WallTime,
};
use orx_priority_queue::*;
use rand::prelude::*;
Expand All @@ -16,12 +16,12 @@ impl TestData {

let mut first_push = Vec::new();
for node in 0..n_first {
first_push.push((node, rng.gen()));
first_push.push((node, rng.random()));
}

let mut second_push_pop = Vec::new();
for node in n_first..(n_first + n_second) {
second_push_pop.push((node, rng.gen()));
second_push_pop.push((node, rng.random()));
}

Self {
Expand Down
8 changes: 5 additions & 3 deletions tests/daryheap.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
mod priority_queue_tests;
#![cfg(not(miri))]

use orx_priority_queue::DaryHeap;
use priority_queue_tests::*;
mod priority_queue_tests;

#[test]
fn test_dary_forall() {
Expand All @@ -17,6 +16,9 @@ fn test_dary_forall() {
}

fn test_dary_for<const D: usize>() {
use orx_priority_queue::DaryHeap;
use priority_queue_tests::*;

let new_heap = DaryHeap::<usize, f64, D>::default;

test_len(new_heap());
Expand Down
10 changes: 6 additions & 4 deletions tests/daryheap_of_indices.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
#![cfg(not(miri))]

mod priority_queue_deckey_tests;
mod priority_queue_tests;

use orx_priority_queue::DaryHeapOfIndices;
use priority_queue_deckey_tests::*;
use priority_queue_tests::*;

#[test]
fn test_dary_forall() {
test_dary_for::<2>();
Expand All @@ -19,6 +17,10 @@ fn test_dary_forall() {
}

fn test_dary_for<const D: usize>() {
use orx_priority_queue::DaryHeapOfIndices;
use priority_queue_deckey_tests::*;
use priority_queue_tests::*;

let new_heap = || DaryHeapOfIndices::<usize, f64, D>::with_index_bound(125);

let change_key = [
Expand Down
10 changes: 6 additions & 4 deletions tests/daryheap_with_map.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
#![cfg(not(miri))]

mod priority_queue_deckey_tests;
mod priority_queue_tests;

use orx_priority_queue::DaryHeapWithMap;
use priority_queue_deckey_tests::*;
use priority_queue_tests::*;

#[test]
fn test_dary_forall() {
test_dary_for::<2>();
Expand All @@ -19,6 +17,10 @@ fn test_dary_forall() {
}

fn test_dary_for<const D: usize>() {
use orx_priority_queue::DaryHeapWithMap;
use priority_queue_deckey_tests::*;
use priority_queue_tests::*;

let new_heap = DaryHeapWithMap::<usize, f64, D>::default;

let change_key = [
Expand Down
12 changes: 6 additions & 6 deletions tests/priority_queue_deckey_tests/change_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@ where
pq.clear();
assert!(pq.is_empty());

let mut rng = rand::thread_rng();
let mut rng = rand::rng();
let mut vec = Vec::new();

// push 100
for node in 0..LEN {
let priority = rng.gen();
let priority = rng.random();
pq.push(node, priority);
vec.push((node, priority));
}

// change keys 100 times
for _ in 0..LEN {
let node = rng.gen_range(0..LEN);
let node = rng.random_range(0..LEN);
let old_key = vec[node].1;
assert_eq!(Some(old_key), pq.key_of(&node));

let new_key = rng.gen::<f64>()
let new_key = rng.random::<f64>()
* match change_key {
ChangeKeyMethod::Decrease => old_key,
_ => 1.0,
Expand All @@ -47,10 +47,10 @@ where
vec[node] = (node, new_key);
}
ChangeKeyMethod::Update => {
let res_updkey = pq.update_key(&node, new_key);
let res_upd_key = pq.update_key(&node, new_key);
assert_eq!(
new_key < old_key,
matches!(res_updkey, ResUpdateKey::Decreased)
matches!(res_upd_key, ResUpdateKey::Decreased)
);
vec[node] = (node, new_key);
}
Expand Down
12 changes: 6 additions & 6 deletions tests/priority_queue_deckey_tests/change_key_or_push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@ where
pq.clear();
assert!(pq.is_empty());

let mut rng = rand::thread_rng();
let mut rng = rand::rng();
let mut vec = (0..100).map(|_| None).collect_vec();

// push 100
for (node, vec_elem) in vec.iter_mut().enumerate() {
if push_at_first_pass(node) {
let priority = rng.gen();
let priority = rng.random();
pq.push(node, priority);
*vec_elem = Some(priority);
}
}

// change keys or push 300 times
for _ in 0..300 {
let node = rng.gen_range(0..100);
let node = rng.random_range(0..100);
let old_key = vec[node];
assert_eq!(old_key, pq.key_of(&node));

let new_key = rng.gen::<f64>()
let new_key = rng.random::<f64>()
* match change_key {
ChangeKeyMethod::Decrease => old_key.unwrap_or(1.0),
_ => 1.0,
Expand All @@ -48,10 +48,10 @@ where
vec[node] = Some(new_key);
}
ChangeKeyMethod::Update => {
let res_updkey_push = pq.update_key_or_push(&node, new_key);
let res_upd_key_push = pq.update_key_or_push(&node, new_key);
assert_eq!(
old_key.map(|old_key| new_key < old_key).unwrap_or(false),
matches!(res_updkey_push, ResUpdateKeyOrPush::Decreased)
matches!(res_upd_key_push, ResUpdateKeyOrPush::Decreased)
);
vec[node] = Some(new_key);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/priority_queue_deckey_tests/key_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ where
assert!(pq.is_empty());
assert_eq!(None, pq.key_of(&0));

let mut rng = rand::thread_rng();
let mut rng = rand::rng();
let mut vec = Vec::new();

for node in 0..100 {
let priority = rng.gen();
let priority = rng.random();
pq.push(node, priority);
vec.push(priority);
}
Expand Down
16 changes: 8 additions & 8 deletions tests/priority_queue_deckey_tests/mixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ where
{
const INITIAL_LEN: usize = 10;
const LEN: usize = 125;
let mut rng = rand::thread_rng();
let mut rng = rand::rng();

pq.clear();
assert!(pq.is_empty());

for _ in 0..INITIAL_LEN {
let push = rng.gen_range(0..LEN);
let priority = rng.gen();
let push = rng.random_range(0..LEN);
let priority = rng.random();
if !pq.contains(&push) {
pq.push(push, priority);
}
Expand All @@ -25,21 +25,21 @@ where
let num_drop = if pq.is_empty() {
0
} else {
rng.gen_range(0..5)
rng.random_range(0..5)
};
let enqueued = pq.iter().map(|x| *x.node()).collect_vec();
let mut to_drop = HashSet::new();
for _ in 0..num_drop {
let ind = rng.gen_range(0..enqueued.len());
let ind = rng.random_range(0..enqueued.len());
to_drop.insert(enqueued[ind]);
}

let mut to_push = vec![];
for _ in 0..to_drop.len() {
let num_push = rng.gen_range(0..5);
let num_push = rng.random_range(0..5);
let mut to_push_for = vec![];
for _ in 0..num_push {
let ind = rng.gen_range(0..LEN);
let ind = rng.random_range(0..LEN);
if !pq.contains(&ind) {
to_push_for.push(ind);
}
Expand All @@ -54,7 +54,7 @@ where
if pq.len() == LEN {
break;
}
let priority = rng.gen();
let priority = rng.random();
if !pq.contains(push) {
pq.push(*push, priority);
}
Expand Down
Loading