Search code examples
prologswi-prolog

Unexpected behaviour of prolog program


So, I am pretty new to prolog (started just yesterday) and I have next problem:

Скласти програму на Пролозі, що встановлює зв’язок по закону Ома (зв'язок між струмом, напругою і опором) для 2 резисторів - послідовних і паралельних.

or

Create a program in Prolog that establishes the relationship between Ohm's law (the relationship between current, voltage and resistance) for 2 resistors - series and parallel.

and I have got to this point:

% vim: set filetype=prolog : 
% problem2.pl

% I1 - струм на резисторі 1 current of resistor 1
% I2 - струм на резисторі 2 current on resistor 2
% V1 - напруга на резисторі 1 voltage on resistor 1
% V2 - напруга на резисторі 2 voltage on resistor 2
% R1 - опір резистора 1 resistance of resistor 1
% R2 - опір резистора 2 resistance of resistor 2
% I  - струм в колі total current 
% V  - напруга в колі total voltage
% R  - опір кола total resistance

% загальні закони ohms law%
% I = U / R

p_ohm(I, I1, I2, V, V1, V2, R, R1, R2) :-
    % паралельне зʼєднання parallel circuit 
    (I1 is V / R1;
    I1 is V1 / R1;
    I1 is V2 / R1;
    I1 is I - I2),

    (I2 is V / R1;
    I2 is V1 / R1;
    I2 is V2 / R1;
    I2 is I - I1),

    (I is I1 + I2;
    I is V /R;
    I is V1 / R;
    I is V2 / R),
    (R1 is V1 / I1;
    R1 is V2 / I1;
    R1 is V / I1;
    R2 is V1 / I2;
    R2 is V2 / I2;
    R2 is V / I2),

    (R is V / I;
    R is 1 / (1 / R1 + 1 / R2)),

    (V is R * I;
    V is V1;
    V is V2
    V is R1 * I1;
    V is R2 * I2),

    ( V1 is V;
    V1 is V2;
    V1 is I1 * R1),

    (V2 is V;
    V2 is V1;
    V2 is I2 * R2).

I have took the parallel circuit properties from here.

And the problem is that this wont work.

➜  ~ swipl b.pl
Welcome to SWI-Prolog (threaded, 64 bits, version 9.0.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- p_ohm(I, I1, 1, 6, V1, V2, R, 1, R2).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR:   [11] 1 is _14408/1
ERROR:   [10] p_ohm(_14434,6,1,6,_14442,_14444,_14446,1,_14450) at /Users/vladyslav/b.pl:25
ERROR:    [9] toplevel_call(user:user: ...) at /opt/homebrew/Cellar/swi-prolog/9.0.4/libexec/lib/swipl/boot/toplevel.pl:1173
?-

Maybe this is because it tries to satisfy I1 is V / R1; but V is undefined at the moment.

?- debug.
true.

[debug]  ?- p_ohm(I, I1, 1, 6, V1, V2, R, 1, R2).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR:   [11] 1 is _5272/1
ERROR:   [10] p_ohm(_5298,6,1,6,_5306,_5308,_5310,1,_5314) at /Users/vladyslav/b.pl:25
ERROR:    [9] toplevel_call(user:user: ...) at /opt/homebrew/Cellar/swi-prolog/9.0.4/libexec/lib/swipl/boot/toplevel.pl:1173
   Exception: (11) 1 is _4162/1 ?

BUT there is ; at the end of I1 is V / R1; that means OR. I don't understand.

The values for p_ohm(I, I1, 1, 6, V1, V2, R, 1, R2) were taken from real physics book problem about two parallel resistors.

I have no idea how to solve that problem in prolog because he tries to satisfy everything (or what?). And also I have poor understanding of its syntax... I cant use predicates as functions to operate on numbers. How to solve the problem at the start of question without suck errors?


Solution

  • Examining the error message:

    ERROR: Arguments are not sufficiently instantiated
    ERROR: In:
    ERROR:   [11] 1 is _14408/1
    ERROR:   [10] ... at /Users/vladyslav/b.pl:25
    

    This means: the error is on line 25.

    Rearrange the equation so that the uninstantiated variable is to the left of the is, and the instantiated variables are on the right - which is how is is meant to be used.

    To handle uninstantiated variables more elegantly, look at:

    • clpfd (for integers, better reasoning)
    • clpBNR (for integers and floating-point numbers)