🍹Branch and bound solution using Rust to calculate an optimal cocktail ingredient list of arbitrary length 🍸

Overview

Calculating an Optimal Cocktail Ingredient List

Tom Explains the Problem

  • You have 100 different ingredients
  • You have 20 cocktails, each of which use 2-6 ingredients
  • Which 5 ingredients maximize the cocktail-making possibilities? What about 10 ingredients?

In this case, we have 117 ingredients, and 104 available cocktails. Can we work out an "ideal" list of cocktail ingredients of an arbitrary length that will maximise the number of unique cocktails that we can make?

This is – in an abstract sense – a classic combinatorial optimisation problem. One way of solving combinatorics problems is "branch and bound" (BnB). This is a Rust implementation of the solution provided by Forest Gregg (reproduced here, lightly edited).

The Rust version doesn't currently have great performance compared to the Python version as it uses a BTreeSet to hold ingredients and these sets – of varying length – are recalculated frequently as the algorithm runs. Unfortunately, BTreeSet uses hashbrown as its hashing algorithm, and it's far too high-quality (slow) compared to the hashing algorithm used for Python's frozenset.

Running the code

Run cargo build --release. The binary (from main.rs) can be run using e.g. ./target/release/branchbound

Performance

By "not great" I mean that the time to calculate a set of 12 ingredients on a Core i5 is:

  • 4.2 wall-clock seconds using Rust 1.66 (around 40 % faster)
  • 6 wall-clock seconds using Python 3.9

This isn't a great result for Rust, and getting to this speed increase involved building lookup tables to map the ingredients and cocktail names to unique i32 values (considerably faster to hash than String), in order to work around the relatively slow std Swisstable-based BTreeSet hash algorithm.

Note that time complexity rises pretty steeply: producing a list of 16 ingredients takes around 95 seconds.

Both versions take around 100k iterations to converge on a 12-ingredient solution. While we previously used a random remaining candidate cocktail to test the quality of our current search – which resulted in a lot of "misses" – we now use a new heuristic: the cocktail among the remaining candidates which is the "least unique" in its ingredients, calculated using a minimum amortized cost function. This has almost halved the number of search rounds, and produces an optimal solution for this heuristic:

  1. Amaretto
  2. Champagne
  3. Cognac
  4. Crème de cassis
  5. Galliano
  6. Gin
  7. Grenadine
  8. Lemon juice
  9. Lime juice
  10. Simple syrup
  11. Triple sec
  12. White rum

Allowing you to mix:

  1. Bacardi cocktail
  2. Between the sheets
  3. Daiquiri
  4. French 75
  5. French Connection
  6. Gimlet
  7. Kir royal
  8. Sidecar
  9. White lady
  10. Yellow bird
You might also like...
Galleries of NFTs using Solana and Rust for contracts

About this Package created to simplify the process of parsing NFTs on Solana. It consists of: Package basic things like fetch all NFTs for specific wa

Thaler's Proofs, Args, and ZK Implemented in Rust using arkworks
Thaler's Proofs, Args, and ZK Implemented in Rust using arkworks

rthaler • Dr. Thaler's book Proofs, Args, and ZK implemented in rust using the arkworks cryptographic rust toolset. Various Zero Knowledge Protocols a

Prefix tree (ordered map and set) data structure using 100% safe Rust

PFX: A 100% safe, blob-oriented prefix tree This crate provides a prefix tree map and set data structure, implemented purely in safe Rust. The API is

shavee is a Program to automatically decrypt and mount ZFS datasets using Yubikey HMAC as 2FA or any USB drive with support for PAM to auto mount home directories.

shavee is a simple program to decrypt and mount encrypted ZFS user home directories at login using Yubikey HMAC or a Simple USB drive as 2FA written in rust.

Nym provides strong network-level privacy against sophisticated end-to-end attackers, and anonymous transactions using blinded, re-randomizable, decentralized credentials.

The Nym Privacy Platform The platform is composed of multiple Rust crates. Top-level executable binary crates include: nym-mixnode - shuffles Sphinx p

An open source desktop wallet for nano and banano with end-to-end encrypted, on chain messaging using the dagchat protocol.
An open source desktop wallet for nano and banano with end-to-end encrypted, on chain messaging using the dagchat protocol.

An open source wallet with end-to-end encrypted, on chain messaging for nano and banano using the dagchat protocol.

Silent monero miner using xmrig and has 0% donation.

Note If this reprository is useful to you in in any shape or form please give it a star. Educational purposes only Don't use this project maliciously.

A black-box raw calldata decoder using only calldata to guess types and parse parameters.
A black-box raw calldata decoder using only calldata to guess types and parse parameters.

Calldata Decoder A black-box raw calldata decoder using only calldata. Based off the topics discussed in DeGatchi's article, Reverse The EVM: Raw Call

🥕 Create a multisig with taproot and spend from it using BDK 🥕

Multisig & carrots This repository contains all the code to build a taproot multisig with your friends, and to spend from it. It's been used first to

Owner
Stephan Hügel
Marie Curie research fellow at TCD: smart cities and climate change. Prev: @casa-ucl. I also work on high-performance computational geometry libraries @georust
Stephan Hügel
Aptos-core strives towards being the safest and most scalable layer one blockchain solution.

Aptos-core strives towards being the safest and most scalable layer one blockchain solution. Today, this powers the Aptos Devnet, tomorrow Mainnet in order to create universal and fair access to decentralized assets for billions of people.

Aptos Labs 4.7k Jan 6, 2023
Harness the power of signify(1) to sign arbitrary git objects

git-signify A tool to sign arbitrary objects in a git repository. Generating keys Signing keys can be generated with signify, from the OpenBSD project

Tiago Carvalho 3 Jul 27, 2023
Doubly-linked list that stores key-node pairs.

key-node-list Doubly-linked list that stores key-node pairs. KeyNodeList is a doubly-linked list, it uses a hash map to maintain correspondence betwee

MaxXing 3 May 4, 2022
Experiments on blockchain technology (also known as Hashed & Zero-trust Verifiable Linked List)

AngeloChain Experiments on blockchain technology (also known as Hashed & Zero-trust Verifiable Linked List) ⚠️ Before We Get Started Before we get sta

Angelo 1 Jan 20, 2022
Parses coin lists according to the coin list standard.

coinlist Parses coin lists according to the coin list standard. License The coinlist crate is licensed under the Apache 2.0 License. Contribution Unle

The Moving Company 2 Jul 10, 2022
A list of open sourced MultiversX SC modules.

Buidly X-Modules About xModules are an open-source library created by builders for builders with the scope of making smart contracts building a bit mo

null 4 Jan 15, 2023
A simple and secure rust command-line tool to protect your text by encrypting and decrypting it using the robust AES-256 algorithm.

Secret Keeper A simple and secure command-line tool to protect your text by encrypting and decrypting it using the robust AES-256 algorithm. Built wit

Kunal Bagaria 9 May 11, 2023
Ethereum (and Ethereum like) indexer using P2P message to fetch blocks and transactions

Ethereum P2P indexer This project is an indexer for Ethereum and Ethereum forks. It takes advantage of the ETH (Ethereum Wire Protocol) to fetch block

null 5 Nov 10, 2023
A prototype project integrating jni rust into Kotlin and using protobuf to make them work together

KotlinRustProto a prototype project integrating jni rust into Kotlin and using protobuf to make them work together How to start add a RPC call in Droi

woo 11 Sep 5, 2022
Port path module (and tests) of nodejs to rust using the same algorithms.

rusty_nodejs_path Port path module (and tests) of nodejs to rust using the same algorithms. crates.io Documents Progress posix path.basename(path[, ex

Yunfei He 10 Sep 25, 2022