rust-random / rand

A Rust library for random number generation.
https://crates.io/crates/rand
Other
1.65k stars 430 forks source link

Add reusable counterpart of WeightedIndex #1459

Open maratik123 opened 3 months ago

maratik123 commented 3 months ago

Background

What is your motivation? There is not any effective WeightedIndex implementation, that does not require new allocation on heap to replace all weighted index values. WeightedIndex::update_weights is only effective on updating small amount of weights.

What type of application is this? Tasks such as Travelling salesman problem for their heuristic and approximation solutions (for example, via Ant colony optimization) require single sampling on each of multiple instances of WeightedIndex with different weights.

Feature request

In commited pull request #1460 I'm trying to add ReusableWeightedIndex with reusable storage to prevent unnecessary allocations

dhardy commented 3 months ago

Is there a reason this can't be a new method like WeightedIndex::replace_weights instead of a whole new distribution type?

The main limitations of adding this functionality to WeightedIndex that I can see:

The biggest limitation of your current approach that I see:

maratik123 commented 3 months ago

Is there a reason this can't be a new method like WeightedIndex::replace_weights instead of a whole new distribution type?

The main limitations of adding this functionality to WeightedIndex that I can see:

  • If, during fill, there is an error, then the result may be left in an invalid state. We would need to handle this somehow.

Yes, this is the main blocker, why I decided to make new implementation. I can not see how to make replace_weights as cheap as possible with such restriction.

The biggest limitation of your current approach that I see:

  • fill returns a temporary object referring to another object; this will be difficult to store in a struct (requiring ouroboros or similar)

I don't wait that this one-time object will require to store in other structs, because it's main target to create weighting fast, make one sampling and drop. If it is required to store object in other struct, then one can use WeightedIndex instead.

dhardy commented 3 months ago

Understood, however I have concerns:

vks commented 3 months ago

Couldn't we just implement WeightedIndex::replace_weights(self, weights: I) -> Result<WeightedIndex> or similar?