Suppose your job was to solve the right triangle shown below, meaning find every side and every angle:
To do so, you'd have to know at something about at least some sides and/or some angles from the start. Wouldn't it be neat if we could tell the computer what we know about the triangle and have it tell us how to find the rest? Let's code some Prolog do so this.
Some immediate questions arise: 1) how do we represent the knowledge of math and trig. in code? 2) How would we code a way of using this knowledge to explain to us how to solve the triangle? It turns out that Prolog is well suited to handle both of these issues.
We won't go so far as to try and have the computer 'discover' math on its own. We'll tell it the relationships that hold for a right triangle, and let it do what it wants with the relationships. There are two parts, 1) the trigonometry and 2) the mathematics.
As for the trig: If we look at the triangle, we see 8 laws that hold: 1) $c^2=a^2+b^2$, 2) $d+e+90=180$, and two each for $\sin$, $\cos$, and $\tan$, of both angles $d$ and $e$.
As for the math: If an equation has $n$ variables in it, if we know $n-1$ of the variables, we can use the equation to find the missing variable. This missing variable, once found, can be thought as a "new knowledge" we can make available to future equations.
Let's focus on the representing the trig knowledge first. We'll define a predicate called rule that works as shown here:
rule([var1,var2,...],text-description)
Move the mouse over a dotted box for more information.
You can see the 8 rule statements in the code below.
rule([c,a,b],'c^2=a^2+b^2') means "if you know any two of c, a, or b, you can use 'c^2=a^2+b^2' to find the third."
rule([d,e],'d+e+90=180') means "if you know either variable d or e, you can use 'd+e+90=180' to solve for the other."
rule([d,a,c],'sin(d)=a/c') means "if you know any two of d, a, or c, you can use 'sin(d)=a/c' to find the third."
You can likely figure the rest out for yourself.f
Now you try. Try running it with the goal advise([b,c]).
Type your code here:
See your results here:
Share your code
Show a friend, family member, or teacher what you've done!
Here is a share link to your code:
Need a hint?
💡 What now?
Now, what about the math? This is all contained in the advise clause. It works like this:
advise(Knowns) :-: advise on how to solve the triangle. We have to put a list of things we know (a-e) into a list called Knowns. So, doing goal: advice([b,c]). tells the code to solve the triangle given that we already know side b and c.
We'll start by asking Prolog to give us a rule in the rule(Needs,Advice) line. This will put the needs of the rule (i.e. the list of variables it needs to work) into variable Needs, and the textual advice for how the rule works into Advice.
Next, we'll get the length of list Needs, to see how many variables it requires (this is $n$ in the discussion above).
Now, we'll find the the intersection of lists Needs and Knowns. Remember, Needs contains the variables the rule needs to work, and Knowns is what we know about the triangle. intersection(Needs,Knowns,Int) puts the variables that occur in both list Needs and list Advice into the list Int. Any variable in either that is not in both will not appear in Int. Hence Int will be a list of variables the given rule needs that we may be able to solve for.
Next, we see if the length of list Int is one less than the number of variables that this rule needs. (This is the $n-1$ check in the discussion above; we want to see if the number of variables we know is one lesss than those needed by a rule.) If this isn't true, the line length(Int,L1) will fail and Prolog will go backwards in the logic chain and find another rule to work with.
If we make it to this line subtract(Needs,Knowns,[CanNowSolveFor]), we know all but one variable needed by the selected rule, so substracting Needs from Knowns will return just the new variable we can now solve for. It'll put it into the Prolog variable CanNowSolveFor.
\+ member(CanNowSolveFor,Knowns) means check that CanNowSolveFor is not already known (\+ means "not" in Prolog).
If it's not a member, we'll print out some advice, and add our newly found knowledge to the list of things we already know via the append([CanNowSolveFor],Knowns,NewKnowns) function.
We'll commit Prolog to its progress on this rule thus far with the !, then call advise again, with our newly updated and expanded list of known variables, so see what other trig. rule it may choose to work with.
If you get this all figured out, try to write your own code that will work for non-right triangles (code up rules involving the Law of Sines and Cosines).