How Jet Built a GPU-Powered Fulfillment Engine with F# and CUDA
devblogs.nvidia.com
devblogs.nvidia.com
I really like it. It still feels very functional but has escape hatches when I want imperative behavior.
I like that I can still write "beautiful" code which feels high level and is expressed in the language of the problem domain, yet can fall back on idiomatic imperative solutions for certain tight loops or data structures.
F# still feels like a toy sometimes but that might only be cause C# is so polished.
Don Syme was a (if not the) driving force behind .NET going with reified generics, for one. Also, back when I was a "C# by day, F# by night" developer, I really felt like F# was being used as an incubator for ideas that were eventually pulled into C# in some form or another. For example, in some respects async/await feels like a domesticated version of the async computation expression.
Lambdas? C# got them later.
Immutable constructor patterns? C# got them later.
A scripting environment? C# is trying.
Pattern matching? C# is trying (but since it's not exhaustive...).
No nulls by default? C# got it later (and less clearly).
It's really impressive how quickly those features have gained mindshare and become 'must haves' despite initial resistance.
Fundamentally, though, the higher order programming features that F# inherits ML give it a maturity and flexibility that C# will just never encompass.
At first I was pretty opposed to both executing functions without using parentheses and also currying as a default. Now I find myself missing those things in the languages I use daily for my job (which sadly, do not include f#).
It might not be do-able in your situation but there are ways you can introduce F# in an incremental, low-risk way. Some ideas here: https://fsharpforfunandprofit.com/posts/low-risk-ways-to-use...
Is it way harder because they provide fulfillment breakdown instantly or something, or because the tech stack is unique?
The article implies that the best solution was brute-force, and therefore they use Genetic Algorithms to search for a "pretty good" solution as opposed to the optimal solution.
Linear Programming on the other hand would find PRECISELY the optimal solution. But there are all kinds of constraints on what kinds of programs Linear Programming can solve.
It seems like this constraint problem can be solved through Linear Programming methods, but I'm not an expert in that algorithm. So maybe Jet.Com is being inefficient here with the algorithm (just a little bit inefficient).
One approach is to use the simplex algorithm, and then simply round the output. A better approach is a recursive meta-algorithm called "branch and bound." Start with a particular variable, and find the lower bound for total price if it is 0 vs if it is 1 by using the simplex algorithm on each side. Enqueue the branch with lower bound for total price. In the next round dequeue the branch with the lowest lower bound; if all the variables are integers return it, otherwise create two branches for another variable, etc. By changing search strategy from "breadth first" to "depth first" you are guaranteed to find a feasible solution sooner. You can also stop early by bounding how much error you are willing to tolerate compared to the lower bound provided by LP.
This is a very standard algorithm though, so I'm sure Jet have tried it. It seems like the number of variables they have is just too large; in the worst case branch and bound is exponential.
This is also a free resource for learning F# in your browser:
https://notebooks.azure.com/Microsoft/libraries/fsharp/html/...
basically click clone, sign in, run & play around.
There are no true dollar costs anywhere in their databases. Also, instead of evaluating all the parallel combinations, they use a branch and bound heuristics.
This is what I bought:
-> $4.22 Q-tips Cotton Swabs 500 ct -> $16.32 iPhone 5/5s, iPhone SE, iPod Touch 5th/6th Gen Adidas Nylon Armband Case - Sports armband for adidas miCoach training system -> $6.95 iBungee Stretch Laces (26-Inch, Black Laces with Black Race Lock) -> $4.79 4 Philips AA Zinc Chloride Double A Batteries R6 1.5V Super Heavy Duty Battery -> $8.10 Monoprice Apple MFi Certified Lightning to USB Charge & Sync Cable, 3ft White -> $89.96 ASICS Men's GEL-Kayano 23 Running Shoes T646N
The order for the phone arm-band was cancelled and everything else shipped _separately_ - I Literally got 5 different packages in the mail - over a week with different items.
Had I gone with Amazon, I would have received - one, maybe two packages with everything. Infact, Jet probably lost money on most of the items they shipped to me.
Us techies sometimes tend to forget the real world (in this case customer experience) while playing with cool technology.
To me, an old fashioned optimizer running on a 15 year old AMD Opteron that delivers the appropriate real-world result is worth more than that F# and CUDA thing that seems to have over-optimized the problem to create a bad customer experience (getting 5 packages in a haphazard way).
Source. Worked on this problem for some years.
Walmart's online orders come from a million places similar to your Jet experience. I used it all the time, when the online prices were identical to the in-store prices. Spend $6 more to get free shipping! Ok, I'll take 50 pounds of cat litter, hope the UPS finance dept thanks you. I wonder why they put a stop to this :(
Something that glpk/gurobi should be used for?
GPU powered algorithm solving is awesome!
But I took a look in Firefox and the site is very informative and the solver is quite snappy.
So...is it naive to think that I can create something similar with MiniZinc (or an equivalent package)? Or will it take too long to even get an answer without CUDA? This seems like a pretty fun weekend project!