1
votes

I'm implementing a Prolog interpreter, and I'd like to include some built-in mathematical functions (sum, product, etc). For example, I would like to be able to make calculations using knowledge bases like this one:

NetForce(F) :- Mass(M), Acceleration(A), Product(M, A, F)
Mass(10) :- []
Acceration(12) :- []

So then I should be able to make queries like ?NetForce(X). My question is: what is the right way to build functionality like this into my interpreter?

In particular, the problem I'm encountering is that, in order to evaluate Sum, Product, etc., all their arguments have to be evaluated (i.e. bound to numerical constants) first. For example, while to code above should evaluate properly, the permuted rule:

NetForce(F) :- Product(M, A, F), Mass(M), Acceleration(A)

wouldn't, because M and A aren't bound when the Product term is processed. My current approach is to simply reorder the terms so that mathematical expressions appear last. This works in simple cases, but it seems hacky, and I would expect problems to arise in situations with multiple mathematical terms, or with recursion. Is there a better solution?

3
I'd suggest: Use an existing Prolog system to build your extensions as meta-interpreters. - false
Yeah, I think that would make sense, but I'm not sure if it will work in the larger context of my project. I'll look into it. - user1604015
Your prolog syntax is off - predicates need to start with lowercase letters, and the :- [] part is invalid syntax... - l4mpi
The example is from the interpreter I have. It's not supposed to work in an existing Prolog system. - user1604015

3 Answers

2
votes

The functionality you are describing exists in existing systems as constraint extensions. There is CLP(Q) over the rationals, CLP(R) over the reals - actually floats, and last but not least CLP(FD) which is often extended to a CLP(Z). See for example library(clpfd).

In any case, starting a Prolog implementation from scratch will be a non-trivial effort, you will have no time to investigate what you want to implement because you will be inundated by much lower level details. So you will have to use a more economical approach and clarify what you actually want to do.

You might study and implement constraint languages in existing systems. Or you might want to use a meta-interpreter based approach. Or maybe you want to implement a Prolog system from scratch. But don't expect that you succeed in all of it.

And to save you another effort: Reuse existing standard syntax. The syntax you use would require you to build an extra parser.

1
votes

You could use coroutining to delay the evaluation of the product:

product(X, A, B) :- freeze(A, freeze(B, X is A*B))

freeze/2 delays the evaluation of its second argument until its first argument is ground. Used nested like this, it only evaluates X is A*B after both A and B are bound to actual terms.

(Disclaimer: I'm not an expert on advanced Prolog topics, there might be an even simpler way to do this - e.g. I think SICStus Prolog has "block declarations" which do pretty much the same thing in a more concise way and generalized over all declarations of the predicate.)

0
votes

Your predicates would not be clause order independent, which is pretty important. You need to determine usage modes of your predicates - what will the usage mode of NetForce() be? If I were designing a predicate like Force, I would do something like

force(Mass,Acceleration,Force):- Force is Mass * Acceleration.

This has a usage mode of +,+,- meaning you give me Mass and Acceleration and I will give you the Force.

Otherwise, you are depending on the facts you have defined to unify your variables, and if you pass them to Product first they will continue to unify and unify and you will never stop.