#匹配 #随机 #da-stb

matchmaker

Rust 库,用于公平地将学生匹配到类别

1 个不稳定版本

0.1.0 2020 年 11 月 13 日

#1311数学 分类中

MPL-2.0 许可证

36KB
592

Matchmaker

这个库可以用来公平地将学生匹配到类别(或活动)。或将学生匹配到学校。或将任何事物匹配到其他事物。

背景

这个库解决的匹配问题在数学上被称为居民问题,是稳定婚姻问题的一个子集。有多个已知的算法可以解决这个问题,每个算法都有其优缺点。关于这个主题的更多信息,请参阅阿姆斯特丹中学入学问题匹配算法

算法

目前,这个库只实现了 延迟接受 - 单一平局处理 算法。这个库的设计允许实现其他算法(只需要完成它)。

使用方法

默认匹配

学生被分配到多个类别,但每个学生只能被分配一次。

use matchmaker::da_stb::match_students;
use matchmaker::{Category, Student};
use rand::thread_rng;
use std::collections::VecDeque;

// Create categories
let cooking = Category::new("Cooking", 10);
let reading = Category::new("Reading", 10);
let walking = Category::new("Walking", 5);

// Create student Bert
// Bert wishes to be placed in category cooking or reading (in that order)
let bert = Student::new(
    "Bert",
    VecDeque::from(vec![cooking.clone(), reading.clone()]),
    Vec::new(),
);

// Create student Suze
// Suze wishes to be placed in category cooking or reading (in that order),
// but does not wish to be placed in category walking
let suze = Student::new(
    "Suze",
    VecDeque::from(vec![reading.clone(), cooking.clone()]),
    Vec::from([walking.clone()]),
);

let mut rng = thread_rng();
let categories = Vec::from([cooking, reading, walking]);

let match_result = match_students(Vec::from([bert, suze]), &categories, &mut rng);

println!("Students matched to categories:");
println!();
for category in &categories {
    println!("{}:", &category.name);
    for student in match_result
        .placed
        .get(&category.name)
        .unwrap_or(&Vec::new())
    {
        println!(" - {}", &student.name);
    }
}

if match_result.not_placable.is_empty() {
    println!();
    println!("All students could be placed.");
}

这将产生以下结果

Students matched to categories:

Cooking:
 - Bert
Reading:
 - Suze
Walking:

All students could be placed.

将学生放置在多个类别中

学生被分配到多个类别。一个学生可以分配到多个类别。

示例

use matchmaker::{Category, Student};
use matchmaker::da_stb::match_students_to_multiple_categories;
use rand::thread_rng;
use std::collections::VecDeque;

// Create categories
let cooking = Category::new("Cooking", 10);
let reading = Category::new("Reading", 10);
let walking = Category::new("Walking", 5);

// Create student Bert
// Bert wishes to be placed in category cooking or reading (in that order)
let bert = Student::new(
    "Bert",
    VecDeque::from(vec![cooking.clone(), reading.clone()]),
    Vec::new(),
);

// Create student Suze
// Suze wishes to be placed in category cooking or reading (in that order),
// but does not wish to be placed in category walking
let suze = Student::new(
    "Suze",
    VecDeque::from(vec![cooking.clone(), reading.clone()]),
    Vec::from([walking.clone()]),
);

let mut rng = thread_rng();
let categories = Vec::from([cooking, reading, walking]);

let match_result = match_students_to_multiple_categories(
    Vec::from([bert, suze]),
    &categories,
    &mut rng);

println!("Students matched to categories:");
println!();
for category in &categories {
    println!("{}:", &category.name);
    for student in match_result
        .placed
        .get(&category.name)
        .unwrap_or(&Vec::new())
    {
        println!(" - {}", &student.name);
    }
}

if match_result.not_placable.is_empty() {
    println!();
    println!("All students could be placed.");
}

这将产生以下结果

Students matched to categories:

Cooking:
 - Suze
 - Bert
Reading:
 - Bert
 - Suze
Walking:
 - Bert

All students could be placed.

// 版权 (c) 2020 Delirious Penguin // // 此源代码形式受 Mozilla 公共许可证,第 2.0 版的约束。如果没有与此文件一起分发 MPL 复制品,您可以从 http://mozilla.org/MPL/2.0/ 获得一份。

依赖项

~1–1.6MB
~34K SLoC