This is the first of a series of posts walking through how I built a robot valet that picks clothing combinations. This post picks safe outfits, but structures the knowledge base that eventually can pick interesting outfits.
Picking my clothes isn’t that hard so why overthink it? I probably wont save enough time spent picking clothes to offset the time it took learn prolog and work on many versions of this knowledge base, but formalizing the clothes picking process means I can generate a week of outfits at once, add rules for how many days before my pants are dirty, and find clothes that don’t fit in any outfit which sounded kind of cool.
Prolog is a logic programming language that allows programmers to define facts and rules and search their program structure to see if particular goals can be satisfied.
% all sandwiches are tasty tasty(X):- sandwich(X). % caprese is a sandwich sandwich(caprese) % is a caprese tasty? tasty(caprese)? > true
Let’s start with how to represent an article of clothing. A really simple knowledge base might have
shirt(blue_button_down_untuckit). shirt(red_tshirt_banana_republic). pants(blue_chinos_jcrew). shoes(chili_leather_loafers). shoes(blue_suede_loafers). outfit(Shirt, Pants, Shoes):- shirt(Shirt), pants(Pants), shoes(Shoes).
which can respond to queries like
?- shirt(X). Shirt = hawkseason_shirt; Shirt = red_tshirt_banana_republic ?- outfit(Shirt, Pants, Shoes). Shirt = hawkseason_shirt, Pants = blue_chinos_jcrew, Shoes = chili_leather_loafers .
In swipl, after each way prolog generates to satisfy the query
outfit(Shirt, Pants, Shoes).
you can terminate the search with
. or ask for more variable assignments that
satisfy the query with
This definition of
outfit doesn’t really generate interesting combinations,
it just generates all combinations including
Shirt = blue_button_down_untuckit, Pants = blue_chinos_jcrew, Shoes = blue_suede_loafers .
Getting more complicated with color
Let’s go back to our “closet” and layer in some more information like color hue, shade, and formality.
shirt(blue_button_down_untuckit, dark). shirt(red_tshirt_banana_republic, dark). pants(blue_chinos_jcrew, dark). pants(gray_chinos_jcrew, dark). shoes(chili_leather_loafers, dark). shoes(blue_suede_loafers, light). outfit(Shirt, Pants, Shoes):- shirt(Shirt, ShirtShade), pants(Pant, PantShade), shoes(Shoe, ShoeShade), ShirtShade = ShoeShade, ShirtShade \= PantShade.
Now when prolog tests out an outfit like
Shirt = blue_button_down_untuckit Pants = gray_chinos_jcrew Shoes = chili_leather_loafers
it will realize that
ShirtShade is the same as
PantShade and reject the
outfit. Queried directly, that is
?- outfit(blue_button_down_untuckit, gray_chinos_jcrew, chili_leather_loafers). false.
With this sort of structure, it’s easy to add rules for concepts like formality
or color. Actually color is a little trickier and worth some focus, but a
simple representation and rules like
PantColor \= ShirtColor, PantColor \= ShoeColor
generates safe outfits, though fails to highlight some more interesting