44 releases (23 stable)

1.4.3 Oct 30, 2024
1.2.4 Sep 29, 2024
1.1.4 Jul 28, 2024
0.6.4 May 16, 2024
0.6.0 Mar 31, 2024

#46 in Machine learning

Download history 2106/week @ 2024-08-04 1284/week @ 2024-08-11 1462/week @ 2024-08-18 950/week @ 2024-08-25 981/week @ 2024-09-01 1080/week @ 2024-09-08 835/week @ 2024-09-15 977/week @ 2024-09-22 1288/week @ 2024-09-29 1021/week @ 2024-10-06 1212/week @ 2024-10-13 1424/week @ 2024-10-20 1647/week @ 2024-10-27 994/week @ 2024-11-03 674/week @ 2024-11-10 646/week @ 2024-11-17

4,140 downloads per month
Used in 3 crates

BSD-3-Clause

170KB
4.5K SLoC

FSRS for Rust

crates.io

This crate contains a Rust API for training FSRS parameters, and for using them to schedule cards.

The Free Spaced Repetition Scheduler (FSRS) is a modern spaced repetition algorithm. It is based on the DSR model proposed by Piotr Wozniak, the creator of SuperMemo.

FSRS-rs is a Rust implementation of FSRS. It is designed to be used in Anki, a popular spaced repetition software. Anki 23.10 has already integrated FSRS as an alternative scheduler.

For more information about the algorithm, please refer to the wiki page of FSRS.


Quickstart

Read up this to determine the optimal retention for your use case.

// Pick to your liking (see above)
let optimal_retention = 0.75;
// Use default parameters/Weights for scheduler
let fsrs = FSRS::new(Some(&[]))?;

// Create a completely new card
let day1_states = fsrs.next_states(None, optimal_retention, 0)?;

// Rate as `hard` on first day
let day1 = day1_states.hard;
dbg!(&day1); // scheduled as `in 4 days`

// Now we review the card 2 days later
let day3_states = fsrs.next_states(Some(day1.memory), optimal_retention, 2)?;

// Rate as `good` this time
let day3 = day3_states.good;
dbg!(day3);

Development

add

#!/bin/sh
cargo fmt
cargo clippy -- -D warnings
git add .

to .git/hooks/pre-commit, then chmod +x .git/hooks/pre-commit

Bindings

Q&A

  • What is the difference with rs-fsrs

    If you want to schedule the card, use [lang]-fsrs or the bindings,

    If you do the optimization, use this crate or its bindings.

  • Why not in one crate but two?

    Calculating the weight involves tensor operations. So the initial data type is different(Tensor vs Vec/Slice). In one crate means use cfg to change type, which is tedious, so here we keep two versions.

    Another reason is, other languages will be hard to port their version when Tensor is used.

  • What about the name?

    At first, there are go-fsrs and other libraries, so rs-fsrs is used.

    Then we want to port the torch version to rust so everyone can calculate on their own devices (tch-rs use libtorch which is too heavy), since the algorithm is called fsrs, add -rs.

Dependencies

~40–75MB
~1.5M SLoC