61 lines
2.4 KiB
Rust
61 lines
2.4 KiB
Rust
//! Scheduling algorithms for satellite task planning.
|
|
//!
|
|
//! A scheduler takes a list of tasks and a set of resources and produces a
|
|
//! schedule. This crate provides a greedy scheduler and the pieces needed to
|
|
//! build others.
|
|
//!
|
|
//! Scheduling with resource constraints is intractable in general: deciding
|
|
//! whether every task fits is a bin packing problem, which is NP-hard. A
|
|
//! satellite planning problem is small, with hundreds of tasks rather than
|
|
//! millions, but an exact search is still impractical for a routine planning
|
|
//! cycle. The scheduler here is therefore a greedy heuristic.
|
|
//!
|
|
//! The algorithm sorts the tasks and places each in the earliest time at
|
|
//! which all of its resources are free together. Tasks are considered in
|
|
//! decreasing order of weighted value, which is a good heuristic: the most
|
|
//! valuable work is placed first and the least valuable fills the remaining
|
|
//! gaps. Mandatory tasks are placed first regardless of their value, because
|
|
//! a task that must run is worth more than any task that may.
|
|
//!
|
|
//! The result is not guaranteed to be optimal, and the crate reports what it
|
|
//! could not place rather than dropping it silently, so that an operator can
|
|
//! see the cost of the plan.
|
|
//!
|
|
//! ```
|
|
//! use apsis_resource::{Resource, ResourceId, ResourceSet, Window};
|
|
//! use apsis_scheduler::Planner;
|
|
//! use apsis_task::{Task, TaskId};
|
|
//!
|
|
//! let mut station = Resource::new(ResourceId::new(0), 1.0);
|
|
//! station.set_windows(&[Window::new(0.0, 1_000.0)]).expect("usable");
|
|
//! let resources = ResourceSet::from_resources(vec![station]).expect("distinct");
|
|
//!
|
|
//! let tasks = vec![Task::new(TaskId::new(0), 60.0)
|
|
//! .try_require(ResourceId::new(0), 1.0)
|
|
//! .expect("the resource is new")];
|
|
//!
|
|
//! let planner = Planner::new();
|
|
//! let result = planner.schedule(&tasks, &resources);
|
|
//! assert_eq!(result.schedule.len(), 1);
|
|
//! assert!(result.is_complete());
|
|
//! ```
|
|
|
|
#![forbid(unsafe_code)]
|
|
#![deny(missing_docs)]
|
|
|
|
mod greedy;
|
|
mod improve;
|
|
mod planner;
|
|
mod sweep;
|
|
|
|
pub use greedy::{
|
|
demand_at, feasible_at, infeasible_tasks, resources_free_at, resources_have_capacity,
|
|
};
|
|
pub use improve::{ImprovementOutcome, ImprovementSettings, improve};
|
|
pub use planner::{PlanOutcome, Planner, SchedulingResult};
|
|
pub use sweep::earliest_feasible_start;
|
|
|
|
pub use apsis_resource::{ResourceId, ResourceSet};
|
|
pub use apsis_schedule::Schedule;
|
|
pub use apsis_task::{PrecedenceGraph, Task, TaskId};
|