Hi There!

I'm Dan Schlegel, an Associate Professor in the Computer Science Department at SUNY Oswego

Project 4 – Constraint Logic Programming

Microproject

To get more acquainted with core.logic, visit https://logic.puzzlebaron.com/ and generate a new logic puzzle. An easy one is good enough to play with. Solve it using core.logic as we did in class! Copy the puzzle narrative and constraints into your source file so you don’t lose them and I can see as well!

Main Project

In the main project you’ll be exploring your microproject further by asking questions about the result, pretending we didn’t have one or more of the constraints and analyzing the effect on the produced options, and posing “what if” style questions of the knowledge base. My examples will all come from the recipe puzzle we did in class, but everything you do should be based on your microproject puzzle.

Part 1: Use core.logic to write a function which takes the output of the solve function and determines if a certain attribute holds. For example, I’d like to ask if the yams cook at 350 degrees, so I might write:
(attribute-holds? (solve-recipe-puzzle) :yam :temp 350)
This function would have to go look through the solve result for [:yam 350 X] where X is some unbound variable. If it’s there, returns true. If not, false. Do the query itself using core.logic instead of usual functional programming constructs. You can use normal functional programming techniques to deal with the return value.

    Part 2: For the rest of the project, we’ll play with a less constrained version of your problem. Let’s remove one or more of the constraints from the puzzle. In the class example, we can just pretend that grandma didn’t remember one or more of the facts about the recipes, leaving us with more than a single resulting possibility. You should play with removing different constraints in your problem. I stored the result of my less-constrained solve function in a variable called multiverse, which I’ll use below.

    Now that we have the multiverse of possibilities, we’ll add some functionality to query it.

    1. Write an attribute-values function which uses core.logic to determine the possible values of an attribute in your multiverse.
      (attribute-values multiverse :meatloaf :temp)
      => (400 350 350 375 350 350 340 340)
      (attribute-values multiverse :meatloaf :time)
      => (40 40 25 40 40 25 30 30)
    2. Write a fraction-of-answers function to compute the fraction of the results for which a provided result holds. Use the previous function and some simple division using standard functional programming techniques. This is a nice excuse to mix functional and logical styles!
      (fraction-of-answers multiverse :meatloaf :time 40)
      => 1/2
      (fraction-of-answers multiverse :meatloaf :temp :400)
      => 1/8

    Part 3: Let’s modify our solve function to take a vector of input constraints. This will let us ask things like “what if the chicken’s time is 35 minutes?” Again using the class example, you might call the solve function as follows:
    (solve-recipe-puzzle [[:chicken :time 35]])
    or
    (solve-recipe-puzzle [[:chicken :time 35] [:meatloaf :temp 400]])

    Your solve function should use the input to create new constraints (taken conjunctively) used in solving the problem. Hint: Generate the list of constraints somehow (some iterative technique like map or for, plus something like cond or case, perhaps?) and use core.logic’s and* to take all constraints in the list conjunctively.