Advanced Tutorial: Encoding LSAT Questions
In this tutorial, we will show you how to use Blawx to solve complicated reasoning problems. To provide lawyers and law students with an example they may be familiar with, we are going to encode a question from the practice LSAT online.
If you want to go to the Blawx live demo, and try the code in this tutorial yourself, you can. The source code from this tutorial is available as a download (right click and “save as”).
The question we are going to encode is question #6 from that exam, which reads as follows:
Exactly three films—Greed, Harvest, and Limelight—are shown during a film club’s festival held on Thursday, Friday, and Saturday. Each film is shown at least once during the festival but never more than once on a given day. On each day at least one film is shown. Films are shown one at a time. The following conditions apply: On Thursday Harvest is shown, and no film is shown after it on that day. On Friday either Greed or Limelight, but not both, is shown, and no film is shown after it on that day. On Saturday either Greed or Harvest, but not both, is shown, and no film is shown after it on that day.
6. Which one of the following could be a complete and accurate description of the order in which the films are shown at the festival?
(A) Thursday: Limelight, then Harvest; Friday: Limelight; Saturday: Harvest
(B) Thursday: Harvest; Friday: Greed, then Limelight; Saturday: Limelight, then Greed
(C) Thursday: Harvest; Friday: Limelight; Saturday: Limelight, then Greed
(D) Thursday: Greed, then Harvest, then Limelight; Friday: Limelight; Saturday: Greed
(E) Thursday: Greed, then Harvest; Friday: Limelight, then Harvest; Saturday: Harvest
One of the reasons that encoding laws in a declarative language is particularly useful is because it allows you to use the same encoding to answer multiple different questions. The LSAT is a good analogy, because the preamble to question 6 is also the preamble for questions 7 through 10.
So we are going to encode the preamble as though we intended to use it for multiple different questions, not just question #6. The preamble is equivalent to the law, the text of question 6 is equivalent to a legal question, and the possible answers are different fact scenarios.
Phase One: What Are We Talking About?
The first step in encoding this question is setting out the names of the categories, objects, and attributes that we are going to be talking about. I decided that I want to be able to talk about days, films, schedules, screenings, and valid screenings.
We start by setting out what a Film is, and what the options are.
Similarly, we set out that Day is a category, and the Days that might be valid.
We add the attributes “after” and “before” to the category “Day” because it will be convenient later to be able to refer to the days that are before or after another day. We name them “after_day” and “before_day” to distinguish them between the similar attribute defined for slots, here.
We decided to model the problem by talking about a screening, which is a showing of a particular film during a particular slot on a particular day. You can see that we have used the three categories we have defined above as the type for the three attributes.
The most complicated part of our ontology will be Schedules. In terms of pure data structure, a Schedule is just a list of screenings. However, in order to simplify our rules, we want to have different attributes that will hold information about some of the conclusions in our rules. You will see how these are used below.
Then we just need to say that there is another type of Schedule, which we will call a Valid Schedule.
Phase 2: What are the Rules?
Now that we have set out the ontology we are going to be using, we can start encoding the rules. The first and most important rule is what qualifies as a valid schedule. Let’s look again at the preamble:
Each film is shown at least once during the festival but never more than once on a given day. On each day at least one film is shown. Films are shown one at a time. The following conditions apply: On Thursday Harvest is shown, and no film is shown after it on that day. On Friday either Greed or Limelight, but not both, is shown, and no film is shown after it on that day. On Saturday either Greed or Harvest, but not both, is shown, and no film is shown after it on that day.
We decided to treat the day-specific rules as separate rules, and to treat the rules that apply to the whole schedule as 4 different rules, for a total of 7 components. Here’s what it looks like:
This rule states that an object in the database, which we will call “A”, is a Valid Schedule if it is a Schedule, and it meets the 7 requirements from the preamble. Now we just need to make 7 rules that will say when each of those criteria is true.
Where the requirement in the rules is that something not happen, (e.g. no movie twice the same day) we will make a rule to find when it does happen, and then use the negation-as-failure version of “not” to say that the condition is met if we can’t find an example of a violation.
Negation is a very complicated topic that we’ll come back to in later tutorials.
Starting with the rule that each film must be shown at least once:
Here you can see we ask whether or not the object A is a Schedule, and if it has three Screenings, B1-3, and all three of the films are in at least one of those screenings. We are relying here on the premise that when we enter data into the database, we will not allow the user to add more than one Film to a Screening object.
Next, we need rule to determine if a film is shown twice the same day. Remember that in our Valid Schedule rule we are negating this, so here we want to check to see if the bad thing DID happen, and the Valid Schedule rule will check to see that it didn’t.
This is a bit unintuitive because of the way Blawx answers question. Blawx will try to find any combination of objects in the database that will make the whole list of statements all true, but it does not assume that because you call one of the variables X and another one Y that you want to refer to different objects.
So one of the possibilities that Blawx will consider is a schedule with a single screening of a single film, and that single screening is both “Y” and “Z” in the above rule.
In order to be explicit that X and Y are supposed to be different, we include the inequality operator block (!==), which means that these two variables do not refer to the same object.
Once you have that, the rest of the rule just asks whether there are two different screenings in the same schedule with the same day and the same film.
Next, we create a rule to see if there is at least one screening per day.
Because we are assuming that a Screening will only be given a single day, film, and slot, and because we are specifying that the days are different, we don’t need to worry that X, Y, and Z might be the same object, here. If your assumptions about the data changed, you might need to add inequality operators to this rule, too.
Now we need a rule to find cases where more than one film is being shown with the same slot and on the same day. You can see that this rule is very similar to the rule that checks for two of the same film on the same day, except now the two things that need to match between different screenings are the day and the slot.
Now we are just left with the Thursday, Friday, and Saturday rules. To make those rules easier to draft, it is helpful to have an attribute on the Schedule object that tells us what the last film on each of the three days is. So we create three helper rules that will set the attributes of
last_saturday. They are all identical, but here is what the “last on Thursday” rule looks like:
This rule is a little complicated, so let’s break it down.
First, it says that the object X needs to be a Schedule, and the object film needs to be a Film, and there needs to be a Screening on Thursday with that film, during the slot “slot”.
Then, it says that there is a “later slot”, which is after “slot”.
Then the last condition says “it is not true that you can find a screening in the same schedule “X”, on Thursday, in one of the later slots.”
Three different rules are created to calculate the last film on thursday, friday, and saturday. Then, we can write the rules for each day.
Thursday’s rule is:
On Thursday Harvest is shown, and no film is shown after it on that day.
So here is our Thursday rule encoded:
Because we know that Harvest can’t be the value of
last_thursday unless it was shown on Thursday, we could actually have eliminated the first 5 of the 6 conditions, there. But it is better style to make your rules look as much as possible as the source material.
The Friday rule is:
On Friday either Greed or Limelight, but not both, is shown, and no film is shown after it on that day.
This is the most complicated rule in the example. You can see that it asks first whether the object “A” is a Schedule, and then looks at two possibilities: either Greed was last, and Limelight wasn’t shown, or vice versa.
Checking to see if the movie was last, we just use our last_friday attribute.
In order to find out whether the other movie was not shown, we use Blawx’s existential qualifier block to try and find any objects that are screenings in the same schedule with Friday and the relevant movie. That block is then wrapped in NAF not, so that what we are asking is “is it not possible to find an object that meets these criteria”?
The Saturday rule is identical, but with the names of the films and the name of the day changed.
Phase 3: What Are the Facts?
The next step in the encoding process is to set out the facts that you want to ask a question about.
Here, we started by defining a Question category and an Answer category, so that we could ask “what is the correct answer to question 6?”
Then, we created an object called Q6 for question six, and created five objects called A6A through A6E, made them schedules, and then created objects for each screening in each schedule, and set out all of the information listed in the possible answers.
These blocks are quite long, but here’s an excerpt of what the block for Answer A looks like:
Now we needed a rule that would define the “correct answer” variable of question 6. Because we are only dealing with one question in this tutorial, we made a simple rule that makes a Schedule object the correct answer if it is a Valid Schedule.
Phase 4: Ask Your Question
So we know the ontology, and we know the rules. We have set out the facts, and now we are ready to ask our question. “What is the correct answer to question 6?”
When you include a variable, Blawx will search the database for all of the objects that can be placed in the necessary variables across all of the rules in order to find a true answer to that question. When you click “Run”, you get the following:
So the reasoner says yes, there is a true answer to that question, and it is when you fill the variable A with the object A6C.
The correct answer is C.
Try It Yourself
If you’d like to see what this code looks like in the Alpha version of Blawx, and see if maybe you can answer some other questions from the exam, the source file is available for download. Download it to your device, start the Blawx live demo, and use the “Load Workspace From File” button to upload the tutorial code.
Please note that because Blawx is in Alpha, it is constantly changing. As it changes, source files for older versions of Blawx may no longer function properly. If you try this file with the current live demo of Blawx, and it doesn’t work, let us know.