0

I tried to write a prolog code that can understand student program written in C#. Now I'm stuck in the process of recognizing the 'if' statement in student's program. For example: The following is the code that I expect from the student.

int d = int.Parse(Console.ReadLine());  // value d is inputted by user
int s = 0;

if (d>0)
    s = 2;
else if (d==0)
    s = 1;
else
    s = 0;

I defined the goal of this expected code as:

goal:- 
   hasVarName(Vid_s, s),
   hasVarName(Vid_d, d),
   hasVarValue(Vid_d, Vd),
   ((not(gt(Vd,0)); hasVarValue(Vid_s, 2)),           %eq: [Vd>0] -> [val_s = 2]
   ((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1)), %eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1]
   ((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0).       %eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0]

The problem is how can I represent the above student code in prolog facts and rules, to find out that the goal is satisfied for any possible conditions.

I tried to change the first part of the student code to become facts like the following, but don't really know how to represent the student's 'if' statement as facts/rules in prolog (I guess, I should not change it to prolog 'if', right?)

hasVarName(varID_d, d)
hasVarValue(varID_d, val_d)   %it is unknown, so I represent it as symbol 'val_d'

hasVarName(varID_s, s)
hasVarValue(varID_s, 0)

And another one, in my goal, when I have comparison such as gt(Vd,0) I think I cannot use the prolog greater than operator, neither Vd> 0 nor Vd @> 0 cause the value in Vd is actually a certain value entered by user, but it is represented as symbolic value (in this case it is: val_d).

Note: using the above goal, I think the defined goal will be satisfied if student code is changed to the following code.

int d = int.Parse(Console.ReadLine());  // value d is inputted by user
int s = 0;

if (d>0)
    s = 2;
else if (d==0)
    s = 1;

or

int d = int.Parse(Console.ReadLine());  // value d is inputted by user
int s = 10;           // any random initialization

if (d>0)
{
    int x = 2;       // unnecessary step, but still Ok.
    s = x;
}
else if (d==0)
    s = 1;
else
    s = 0;

But again, I need help/idea how this code can be represented in prolog as action/rule/fact to meet the goal.

Any help is really appreciated.

Many thanks

false
  • 10,264
  • 13
  • 101
  • 209
Budi Hartanto
  • 337
  • 3
  • 14

2 Answers2

0

I guess you tried to model if-then-else via implication, using the following boolean identity:

A -> B == ~A v B.

Instead of using conjunctions of implications, it is easier to use disjunction to choose between branches, and conjunction along the control flow. But that you exclude previous if-conditions via negation is still necessary.

Take your example:

if (d>0)
   s = 2;
else if (d==0)
   s = 1;
else
   s = 0;

You can use CLP( * ) to model it. Add extra variables so that variables are not overridden, but this is not a problem in the small above snippet. In CLP( * ) the above snippet becomes, I am using CLP(FD) for simplicity:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.3.0)
Copyright (c) 1990-2012 University of Amsterdam, VU Amsterdam
?- use_module(library(clpfd)).
?- [user].
that_if(D, S) :-
   (D #> 0, S #= 2;
    D #=< 0, D #= 0, S #= 1;
    D #=< 0, D #\= 0, S #= 0)
^D

In a decent CLP( * ) system you can arbitrarily instantiate or constrain D or S in a query. We get for example already in CLP(FD):

/* What conditions give result S #= 1 ? */
?- S #= 1, that_if(D, S).
S = 1,
D = 0 .

/* What results give condition D #= 1 */
?- D #= 1, that_if(D, S).
D = 1,
S = 2 ;
false.

/* What conditions give a result S #=< 1 */
?- S #=< 1, that_if(D, S).
S = 1,
D = 0 ;
S = 0,
D in inf.. -1.

/* What results give a condition D #>= 0 */
?- D #>= 0, that_if(D, S).
S = 2,
D in 1..sup ;
D = 0,
S = 1 ;
false.

Bye

  • CLP it's interesting, but I think that a newbie could **really** have hard time to make sense of it. – CapelliC Oct 25 '12 at 13:27
  • Not my opinion: Neither do I know whether Budi Hartanto is a newbie nor do I have statistical data that CLP( * ) is particularly hard. CLP( * ) should be simpler, since it is more declarative. –  Oct 25 '12 at 14:14
  • Further without some CLP( * ) not much can be verified. If you have int d = int.Parse(Console.ReadLine()); then data can be arbitrary, and standard Prolog exhaustive search will practically not work to answer your queries. You need something more symbolic like CLP( * ). –  Oct 25 '12 at 14:18
  • Hi Cookie Monster, Thanks for the suggested solution. The problem is, in my case, I would never know what is the value of d cause I will never run the student code. I just need to analize that the student code contain enough plans (conditions) to solve the problem given to him. Therefore, I will never know the value of D and in my example I just simply assign val_d as a symbolic representation of the content of variable d. So, my problem in this case is more like checking the student's plan (code) if it can be used to solve the problem given to him. – Budi Hartanto Oct 25 '12 at 21:45
  • CLP( * ) does also not assign values, unless for example in CLP(FD) you use labeling. But an answer such as D in 1..sup is not a value assignment but a domain range for the variable. But you would need a little bit more coding, and eventually reified constraints, to get at more precise responses from your CLP( * ) relative to the question you have. For example checking spec_if(D,S) <-> code_if(D,S). –  Oct 26 '12 at 07:09
  • I think I'll take a look deeper on CLP(*). Any suggestion for me to start learning the CLP(*)? BTW, it can be combined into SWI-Prolog right? Cheers – Budi Hartanto Oct 27 '12 at 08:03
  • BTW, After several searching, I can't find any information about CLP(*). Is the star in there is one version of CLP or the star in there means 'any' CLP version? (whether it is CLP(FD), CLP(R), or other). Thanks – Budi Hartanto Oct 27 '12 at 20:58
  • The * is a placeholder, for the various incarnations. By CLP(*) I denote the general idea of constraint logic programming. In which language do you look for material. German, English, etc..? –  Oct 28 '12 at 16:26
  • Ok. I'm looking for material in English. Thanks – Budi Hartanto Oct 28 '12 at 21:02
  • This is a quick intro into CLP(R). It uses another syntax, not X #= 2, but {X=2}: http://www.youtube.com/watch?v=33S6qap_SIU –  Nov 02 '12 at 00:53
0

Usually a language implementation requires an abstract syntax tree, where it's convenient to specify the semantic actions that implements the constructs we are allowed to express.

You seem skipping the phase of building the syntax tree, and (by hand?) represent the intermediate level of the program.

If you stick to such medium level representation, you can use a recursive term (an abstract tree, in effect) like if(Condition, Then, Else) where each var it's in turn a syntax tree.

Otherwise, a more practical representation (usually applied for imperative language), use the concepts of basic blocks (an instruction sequence without jumps) and then labels, to describe the execution flow.

The result it's a graph, and the behaviour of the program is determined by the 'topology' of that representation.

goal:- 
   hasVarName(Vid_s, s),
   hasVarName(Vid_d, d),
   hasVarValue(Vid_d, Vd),

   %eq: [Vd>0] -> [val_s = 2]
   ((not(gt(Vd,0)); hasVarValue(Vid_s, 2), goto(label(0))),

   %eq: [~(Vd>0)^(Vd=0)] -> [val_s = 1]
   ((gt(Vd,0); not(eq(Vd,0)); hasVarValue(Vid_s, 1), goto(label(0))),

   %eq: [~(Vd>0)^~(Vd=0)] -> [val_s = 0]
   ((gt(Vd,0); eq(Vd,0); hasVarValue(Vid_s, 0)), % the goto is useless here...

   label(0),
   .....

Note that I didn't pay any attention to describe correctly your sample program, just placed the jumps to show this possibility...

edit I think that the general problem can't be solved, being equivalent to the halting problem for a Turing Machine. For the particular case at hand, without loops, I would attack the problem using abstract interpretation on the AST. I.e. an interpreter that computes what's interesting.

If it's feasible depends on the generality of your target programs. You should be able to partition the integer domain for each variable involved in each condition point. Things become rapidly complex...

Specifically, at the condition point of the IF THEN ELSE attempt to partition the domain. Using such approach, let Prolog execute the IF testing both branches, propagating the values. But, as I said, is not really easy...

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • Hi Chac, thanks for the suggested solution. Can you explain a bit more of your suggestion? For your information, this is the whole thing that I did: I have a C# program that read the student C# program. In my C# program, I have the AST of the student's code. From this AST, I create prolog clauses to let prolog determine if the goal that I set up for the student's task is satisfied or not. So, I have the AST ready in my C# program, but I don't really know how to present it in prolog to connect it with my goal. Or maybe the way I define my goal is not correct? Thanks – Budi Hartanto Oct 25 '12 at 22:03