Skip to content

Commit

Permalink
Bump version to 1.22.0
Browse files Browse the repository at this point in the history
* `breaking` replace MDP with multi-armed bandit RL algorithm
* change `stops.activity.time.start` not to include waiting time
* improve required break functionality
* improve managing packages with cargo's workspace
* update dependencies
* `breaking`: refactor internal models to simplify cost/telemetry handling
* `breaking` change required break definition to support time range
* change duration in csv import command from minutes to seconds
* `breaking` use `GenericError` instead of `String` within `Result`
* more experimental plots in `heuristic-research` playground
* geojson output if the library is used from interop api
  • Loading branch information
reinterpretcat committed Aug 8, 2023
1 parent bcf5505 commit 957b641
Show file tree
Hide file tree
Showing 13 changed files with 56 additions and 43 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file.

## [Unreleased]


## [v1.22.0]- 2023-08-08

This release focuses on algorithmic and some feature changes

### Changed
Expand Down Expand Up @@ -665,7 +668,8 @@ with Self Organizing MAps and eXtrAs (pronounced as "rosomaha", from russian "р

- Initial commit

[Unreleased]: https://github.com/reinterpretcat/vrp/compare/v1.21.1...HEAD
[Unreleased]: https://github.com/reinterpretcat/vrp/compare/v1.22.0...HEAD
[v1.22.0]: https://github.com/reinterpretcat/vrp/compare/v1.21.1...v1.22.0
[v1.21.1]: https://github.com/reinterpretcat/vrp/compare/v1.21.0...v1.21.1
[v1.21.0]: https://github.com/reinterpretcat/vrp/compare/v1.20.0...v1.21.0
[v1.20.0]: https://github.com/reinterpretcat/vrp/compare/v1.19.2...v1.20.0
Expand Down
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ authors:
given-names: "Ilya"
orcid: "https://orcid.org/0000-0002-7613-7412"
title: "Rosomaxa, Vehicle Routing Problem Solver"
version: 1.21.1
version: 1.22.0
doi: 10.5281/zenodo.4624037
date-released: 2022-05-13
date-released: 2023-08-08
url: "https://github.com/reinterpretcat/vrp"
16 changes: 8 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ members = [
]

[workspace.package]
version = "1.21.1"
version = "1.22.0"
authors = ["Ilya Builuk <[email protected]>"]
license = "Apache-2.0"
keywords = ["vrp", "optimization"]
Expand All @@ -24,16 +24,16 @@ edition = "2021"

[workspace.dependencies]
# internal dependencies
rosomaxa = { path = "rosomaxa", version = "0.6.0" }
vrp-core = { path = "vrp-core", version = "1.21.1" }
vrp-scientific = { path = "vrp-scientific", version = "1.21.1" }
vrp-pragmatic = { path = "vrp-pragmatic", version = "1.21.1" }
vrp-cli = { path = "vrp-cli", version = "1.21.1" }
rosomaxa = { path = "rosomaxa", version = "0.7.0" }
vrp-core = { path = "vrp-core", version = "1.22.0" }
vrp-scientific = { path = "vrp-scientific", version = "1.22.0" }
vrp-pragmatic = { path = "vrp-pragmatic", version = "1.22.0" }
vrp-cli = { path = "vrp-cli", version = "1.22.0" }

# external dependencies
hashbrown = "0.14.0"
serde = { version = "1.0.175", features = ["derive"] }
serde_json = "1.0.103"
serde = { version = "1.0.183", features = ["derive"] }
serde_json = "1.0.104"
rand = { version = "0.8.5", features = ["small_rng"] }
rayon = "1.7.0"
rustc-hash = "1.1.0"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
![build](https://github.com/reinterpretcat/vrp/actions/workflows/build.yaml/badge.svg)
[![downloads](https://img.shields.io/crates/d/vrp-core)](https://crates.io/crates/vrp-core)
[![codecov](https://codecov.io/gh/reinterpretcat/vrp/branch/master/graph/badge.svg)](https://codecov.io/gh/reinterpretcat/vrp)
[![dependency status](https://deps.rs/crate/vrp-cli/1.21.1/status.svg)](https://deps.rs/crate/vrp-cli/1.21.1)
[![dependency status](https://deps.rs/crate/vrp-cli/1.22.0/status.svg)](https://deps.rs/crate/vrp-cli/1.22.0)
[![DOI](https://zenodo.org/badge/238436117.svg)](https://zenodo.org/badge/latestdoi/238436117)

![VRP example](docs/resources/vrp-example.png "VRP with Route Balance")
Expand Down Expand Up @@ -68,7 +68,7 @@ Another fast way to try vrp solver on your environment is to use `docker` image
* **run public image** from `Github Container Registry`:

```bash
docker run -it -v $(pwd):/repo --name vrp-cli --rm ghcr.io/reinterpretcat/vrp/vrp-cli:1.21.1
docker run -it -v $(pwd):/repo --name vrp-cli --rm ghcr.io/reinterpretcat/vrp/vrp-cli:1.22.0
```

* **build image locally** using `Dockerfile` provided:
Expand Down
13 changes: 8 additions & 5 deletions docs/src/concepts/pragmatic/problem/vehicles.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,22 @@ Each shift can have the following properties:
vehicle has to navigate first to one of these places to load goods with dispatching constraints.
Check example [here](../../../examples/pragmatic/basics/dispatch.md).
- **breaks** (optional) a list of vehicle breaks. There are two types of breaks:
* required: this break is guaranteed to be assigned at cost of flexibility. It has the following properties:
- `time` (required): a fixed time or offset when the break should happen
* __required__: this break is guaranteed to be assigned at cost of flexibility. It has the following properties:
- `time` (required): a fixed time or offset range when the break should happen specified by `earliest` and `latest` properties.
The break will be assigned not earlier, and not later than the range specified.
- `duration` (required): duration of the break
* optional: although such break is not guaranteed for assignment, the algorithm has more flexibility for assignment.
* __optional__: although such break is not guaranteed for assignment, it has some advantages over required break:
- aribatry break location is supported
- the algorithm has more flexibility for assignment
It is specified by:
- `time` (required): time window or interval after which a break should happen (e.g. between 3 or 4 hours after start).
- `places`: list of alternative places defined by `location` (optional), `duration` (required) and `tag` (optional).
If location of a break is omitted then break is stick to location of job served before break.
If location of a break is omitted then break is stick to location of a job served before break.
- `policy` (optional): a break skip policy. Possible values:
* `skip-if-no-intersection`: allows to skip break if actual tour schedule doesn't intersect with vehicle time window (default)
* `skip-if-arrival-before-end`: allows to skip break if vehicle arrives before break's time window end.

Please note that break is a soft constraint and can be unassigned in some cases due to other hard constraints, such
Please note that optional break is a soft constraint and can be unassigned in some cases due to other hard constraints, such
as time windows. You can control its unassignment weight using specific property on `minimize-unassigned` objective.
See example [here](../../../examples/pragmatic/basics/break.md)
- **reloads** (optional) a list of vehicle reloads. A reload is a place where vehicle can load new deliveries and unload
Expand Down
2 changes: 1 addition & 1 deletion docs/src/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Another fast way to try vrp solver on your environment is to use `docker` image
* **run public image** from `Github Container Registry`:

```bash
docker run -it -v $(pwd):/repo --name vrp-cli --rm ghcr.io/reinterpretcat/vrp/vrp-cli:1.21.1
docker run -it -v $(pwd):/repo --name vrp-cli --rm ghcr.io/reinterpretcat/vrp/vrp-cli:1.22.0
```

* **build image locally** using `Dockerfile` provided:
Expand Down
2 changes: 1 addition & 1 deletion experiments/heuristic-research/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ plotters = { version = "0.3.5", default-features = false, features = [
"all_series",
] }
plotters-canvas = "0.3.0"
itertools = "0.10.5"
itertools = "0.11.0"
wasm-bindgen = "0.2.87"
web-sys = { version = "0.3.64", features = ["HtmlCanvasElement", "console"] }
lazy_static = "1.4.0"
9 changes: 6 additions & 3 deletions experiments/heuristic-research/src/solver/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ fn create_rosomaxa_state(network_state: NetworkState, fitness_values: Vec<f64>)
#[derive(Default, Serialize, Deserialize)]
pub struct SearchResult(pub usize, pub f64, pub (usize, usize), pub usize);

/// Heuristic state result represented as (state idx, alpha, beta, mu, v, n).
/// Heuristic state result represented as (state idx, name idx, alpha, beta, mu, v, n).
#[derive(Default, Serialize, Deserialize)]
pub struct HeuristicResult(pub usize, pub usize, pub f64, pub f64, pub f64, pub f64, pub usize);

Expand Down Expand Up @@ -189,19 +189,22 @@ impl HyperHeuristicState {

let generation: usize = fields[0].parse().unwrap();
let state = fields[1].clone();
let idx = fields[2].parse().unwrap();
let name = fields[2].clone();
let alpha = fields[3].parse().unwrap();
let beta = fields[4].parse().unwrap();
let mu = fields[5].parse().unwrap();
let v = fields[6].parse().unwrap();
let n = fields[7].parse().unwrap();

insert_to_map(&mut states, state.clone());
insert_to_map(&mut names, name.clone());

let state = states.get(&state).copied().unwrap();
let name = names.get(&name).copied().unwrap();

data.entry(generation)
.or_insert_with(Vec::default)
.push(HeuristicResult(state, idx, alpha, beta, mu, v, n));
.push(HeuristicResult(state, name, alpha, beta, mu, v, n));

data
});
Expand Down
2 changes: 1 addition & 1 deletion rosomaxa/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rosomaxa"
version = "0.6.0"
version = "0.7.0"
description = "A rosomaxa algorithm and other building blocks for creating a solver for optimization problems"
authors.workspace = true
license.workspace = true
Expand Down
31 changes: 17 additions & 14 deletions rosomaxa/src/hyper/dynamic_selective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ where
}
}

type SlotMachines<'a, C, O, S> = Vec<SlotMachine<SearchAction<'a, C, O, S>, DefaultDistributionSampler>>;
type SlotMachines<'a, C, O, S> = Vec<(SlotMachine<SearchAction<'a, C, O, S>, DefaultDistributionSampler>, String)>;

#[derive(PartialEq, Eq, Hash, Clone)]
enum SearchState {
Expand Down Expand Up @@ -206,10 +206,13 @@ where
.into_iter()
.map(|(operator, name, _)| {
// TODO use initial weight as prior mean estimation?
SlotMachine::new(
1.,
SearchAction { operator, operator_name: name.to_string() },
DefaultDistributionSampler::new(environment.random.clone()),
(
SlotMachine::new(
1.,
SearchAction { operator, operator_name: name.to_string() },
DefaultDistributionSampler::new(environment.random.clone()),
),
name,
)
})
.collect::<Vec<_>>();
Expand Down Expand Up @@ -242,8 +245,8 @@ where
.slot_machines
.get(&from)
.and_then(|slots| {
random_argmax(slots.iter().map(|slot| slot.sample()), self.random.as_ref())
.and_then(|slot_idx| slots.get(slot_idx).map(|slot| (slot_idx, slot)))
random_argmax(slots.iter().map(|(slot, _)| slot.sample()), self.random.as_ref())
.and_then(|slot_idx| slots.get(slot_idx).map(|(slot, _)| (slot_idx, slot)))
})
.expect("cannot get slot machine");

Expand All @@ -257,7 +260,7 @@ where
let from = &feedback.sample.transition.0;

if let Some(slots) = self.slot_machines.get_mut(from) {
slots[feedback.slot_idx].update(feedback);
slots[feedback.slot_idx].0.update(feedback);
}

self.tracker.observe_sample(generation, feedback.sample.clone())
Expand All @@ -270,11 +273,11 @@ where
}

self.slot_machines.iter().for_each(|(state, slots)| {
slots.iter().enumerate().map(|(idx, slot)| (idx, slot.get_params())).for_each(
|(idx, (alpha, beta, mu, v, n))| {
slots.iter().map(|(slot, name)| (name.clone(), slot.get_params())).for_each(
|(name, (alpha, beta, mu, v, n))| {
self.tracker.observe_params(
generation,
HeuristicSample { state: state.clone(), idx, alpha, beta, mu, v, n },
HeuristicSample { state: state.clone(), name, alpha, beta, mu, v, n },
);
},
)
Expand Down Expand Up @@ -304,11 +307,11 @@ where
}

f.write_fmt(format_args!("heuristic:\n"))?;
f.write_fmt(format_args!("generation,state,idx,alpha,beta,mu,v,n\n"))?;
f.write_fmt(format_args!("generation,state,name,alpha,beta,mu,v,n\n"))?;
for (generation, sample) in self.agent.tracker.heuristic_telemetry.iter() {
f.write_fmt(format_args!(
"{},{},{},{},{},{},{},{}\n",
generation, sample.state, sample.idx, sample.alpha, sample.beta, sample.mu, sample.v, sample.n
generation, sample.state, sample.name, sample.alpha, sample.beta, sample.mu, sample.v, sample.n
))?;
}

Expand Down Expand Up @@ -438,7 +441,7 @@ struct SearchSample {

struct HeuristicSample {
state: SearchState,
idx: usize,
name: String,
alpha: f64,
beta: f64,
mu: f64,
Expand Down
6 changes: 3 additions & 3 deletions vrp-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@ serde_json.workspace = true
csv = { version = "1.2.2", optional = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
clap = "4.3.19"
clap = "4.3.21"
ctrlc = { version = "3.4.0", features = ["termination"] }
num_cpus = "1.16.0"

# see https://github.com/xd009642/tarpaulin/issues/1092
[target.'cfg(all(not(target_arch = "wasm32"), not(tarpaulin)))'.dependencies]
pyo3 = { version= "0.19.1", features=["extension-module"], optional = true }
pyo3 = { version= "0.19.2", features=["extension-module"], optional = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = { version = "0.2.87" }
serde-wasm-bindgen = "0.5.0"
js-sys = "0.3.64"

[dev-dependencies]
tempfile = "3.7.0"
tempfile = "3.7.1"
2 changes: 1 addition & 1 deletion vrp-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ mod cli {

pub fn get_app() -> Command {
Command::new("Vehicle Routing Problem Solver")
.version("1.21.1")
.version("1.22.0")
.author("Ilya Builuk <[email protected]>")
.about("A command line interface to Vehicle Routing Problem solver")
.subcommand(get_analyze_app())
Expand Down
2 changes: 1 addition & 1 deletion vrp-pragmatic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ serde.workspace = true
serde_json.workspace = true
rand.workspace = true

time = { version = "0.3.23", features = ["parsing", "formatting"] }
time = { version = "0.3.25", features = ["parsing", "formatting"] }

[dev-dependencies]
proptest = "1.2.0"
Expand Down

0 comments on commit 957b641

Please sign in to comment.