Created
March 5, 2014 23:45
-
-
Save Engelberg/9379157 to your computer and use it in GitHub Desktop.
Optimizing allocation with loco
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns mark.loco.grants | |
(:use loco.core loco.constraints)) | |
; Use whatever scoring function you want for the various | |
; applicants, but ultimately, you want to assemble this | |
; information into a data structure. | |
(def applicants | |
[{:name "Alex", :score 5, :grant-request 120} | |
{:name "David", :score 4, :grant-request 100} | |
{:name "Mark", :score 3, :grant-request 80}]) | |
(def n (count applicants)) | |
(def budget 200) | |
; We'll be dealing with fractions, but our values need to be integers, | |
; so we need a scaling factor to multiply the fractions by before | |
; truncating to integers. | |
(def scale 1000) | |
; variable [:allocation n] is how much money to allocate to | |
; the applicant at the nth position of the applicants vector | |
(def allocation-vars | |
(for [i (range n)] [:allocation i])) | |
(def grant-constraints | |
; Don't give any person more than they asked for | |
(for [i (range n)] | |
($in [:allocation i] 0 (:grant-request (applicants i))))) | |
(def budget-constraint | |
; Don't spend more than the budget permits | |
($<= (apply $+ allocation-vars) budget)) | |
(def all-constraints (conj grant-constraints budget-constraint)) | |
; If you assume that the probability of someone coming | |
; is the allocation they received divided by the grant | |
; requested, then the "value" of each dollar given to | |
; a person is their score divded by the size of their grant request. | |
(def grant-values | |
(for [i (range n)] | |
(int (* scale (/ (:score (applicants i)) | |
(:grant-request (applicants i))))))) | |
(solution all-constraints | |
:maximize (apply $+ (map $* allocation-vars grant-values))) | |
; The global scalar constraint should be equivalent and more efficient | |
; but there appears to be a bug in loco that prevents scalar | |
; from being used with maximize. I have filed an issue on this. | |
;(solution all-constraints | |
; :maximize ($scalar allocation-vars grant-values)) |
The :maximize ($scalar allocation-vars grant-values)
version works in 0.1.1-SNAPSHOT,
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
One could also scale the grant-values dynamically, rather than by a hard-coded value, by whatever scaling factor gives you a spread of, say, 100, between the minimum and maximum values: