Expert System for Picking Outfits (#1)
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
Getting Started
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 .
<?xml version=”1.0” encoding=”UTF-8” standalone=”no”?>
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
<?xml version=”1.0” encoding=”UTF-8” standalone=”no”?>
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
combinations.
<?xml version=”1.0” encoding=”UTF-8” standalone=”no”?>