# Making a predicate true as default and functional

**URL:** <https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657>\
**Category:** Help!\
**Tags:** scasp\
**Created:** [June 23, 2023, 9:35pm UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657 "2023-06-23T21:35:52Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![mars](https://avatars.discourse-cdn.com/v4/letter/m/e56c9b/32.png) [@mars](https://swi-prolog.discourse.group/u/mars)\
**Post date:** [June 23, 2023, 9:35pm UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/1 "2023-06-23T21:35:52Z")

</div>

I have a rule that checks whether a thing is big enough:

```prolog
big_enough(X) :- size(X,Y), Y #> 2.

```

If the size of a thing `a` is not specified, I want the answer to the query `?- big_enough(a).` to be a model containing `size(a, Y | {Y #> 2})` for some variable Y. Therefore, I want that everything has every size until it is stated to have a specific size. Then, it should have this size and no other. Here is my attempt:

```prolog
size(X,Y) :- has_size(X,Y). 
size(X,Y) :- not -size(X,Y). 
-size(X,Y1) :- has_size(X,Y2), Y1 \= Y2. 

```

In order to avoid ending up in a loop, the “stating a thing to have a specific size” is done indirectly through the predicate `has_size`.

Querying (in ciao) `?- big_enough(a).` gives the model

```prolog
{ big_enough(a), size(a,Var0 | {Var0 #> 2}), not -size(a,Var0 | {Var0 #> 2}), not -size(Var1,Var2) }.

```

It contains `size(a,Var0 | {Var0 #> 2})` as expected. I don’t understand why it contains `not -size(Var1,Var2)`.

When the size of “a” is specified through the fact

```prolog
size(a,3).

```

I expect the answer to the query `?- big_enough(a).` to be exactly one model. However, I get two nearly identical models:

```prolog
{ big_enough(a), size(a,3), has_size(a,3), not -size(Var0 | {Var0 \= a},Var1), not has_size(Var0 | {Var0 \= a},Var2), not -size(a,3), not has_size(a,Var3 | {Var3 \= 3}), -size(a,Var4 | {Var4 \= 3}), not size(a,Var4 | {Var4 \= 3}), not has_size(a,Var4 | {Var4 \= 3}) }

{ big_enough(a), size(a,3), not -size(a,3), not has_size(a,Var0 | {Var0 \= 3}), has_size(a,3), not -size(Var1 | {Var1 \= a},Var2), not has_size(Var1 | {Var1 \= a},Var3), not has_size(a,Var4 | {Var4 \= 3}), -size(a,Var5 | {Var5 \= 3}), not size(a,Var5 | {Var5 \= 3}), not has_size(a,Var5 | {Var5 \= 3}) }

```

Can someone help me understand this behaviour? I would also appreciate tips on better ways to do this.

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![anon419083](https://avatars.discourse-cdn.com/v4/letter/a/53a042/32.png) [@anon419083](https://swi-prolog.discourse.group/u/anon419083)\
**Post date:** [June 24, 2023, 11:25am UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/2 "2023-06-24T11:25:20Z")

</div>

Hi mars,  
I can’t figure out really in what sort of computations you’re stuck, but…the only meaningful thing that comes to my mind is that usually (in natural languages) determining the meaning of adjectives like “big”, “tall”, “small”, etc. is not so straightforward, because it depends a lot on the comparison class you choose (or that you have in mind, more or less consciously, talking about natural languages). And I guess that also determining if something is “big enough” depends a lot on what one aims at.  
Best regards

---

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [June 24, 2023, 11:42am UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/3 "2023-06-24T11:42:20Z")

</div>

_Size_ is a property of a thing. So just use:

```prolog
big_enough(thing(_Name, Size)) :-
    freeze(Size, Size > 2).

```

Results:

```prolog
?- big_enough(thing(elephant, Size)), Size = 3.
Size = 3.

?- big_enough(thing(mouse, Size)), Size = 1.
false.

?- big_enough(thing(alien, Unknown)).
freeze(Unknown, Unknown>2).

```

---

<div class="post-metadata">

**Author:** ![mars](https://avatars.discourse-cdn.com/v4/letter/m/e56c9b/32.png) [@mars](https://swi-prolog.discourse.group/u/mars)\
**Post date:** [June 24, 2023, 4:20pm UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/4 "2023-06-24T16:20:21Z")

</div>

The background is that I’m trying to formalize a regulation that lists the requirements cars must fulfill in order to drive on different kinds of roads. I want to be able to query in all directions: Both “Is this car allowed to drive on this road?” and “What sizes of cars are allowed on this road?”. In the latter case, the idea is to make the size-predicate true for all sizes, so that we get a model with a set expression that corresponds to the requirement. But in the former case, when the size is given, the size-predicate should be false for every other size, so that we get no models when the requirements are not fulfilled.

---

<div class="post-metadata">

**Author:** ![mars](https://avatars.discourse-cdn.com/v4/letter/m/e56c9b/32.png) [@mars](https://swi-prolog.discourse.group/u/mars)\
**Post date:** [June 24, 2023, 4:28pm UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/5 "2023-06-24T16:28:51Z")

</div>

That looks interesting, thank you! I didn’t know about freeze.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [June 28, 2023, 10:25am UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/6 "2023-06-28T10:25:35Z")

</div>

This started as s(CASP) problem. Yes, possibly normal Prolog, possibly extended with tabling and/or constraints could be an alternative. You’ll have to make up your mind though. s(CASP) implements _Stable Model Semantics_, while pure Prolog only has negation-as-failure or, using tabling, _Well Founded Semantics_. If negation is important to you, you need to consider this. If you don’t need s(CASP) for its reasoning about negation, pure Prolog is probably better.

---

<div class="post-metadata">

**Author:** ![mars](https://avatars.discourse-cdn.com/v4/letter/m/e56c9b/32.png) [@mars](https://swi-prolog.discourse.group/u/mars)\
**Post date:** [June 28, 2023, 12:18pm UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/7 "2023-06-28T12:18:01Z")

</div>

Thank you for this comment! I’m quite new to all of this and still pondering about the implications of using s(CASP) vs pure Prolog. According to my current understanding, s(CASP) fits my use case best. So I’m still looking for a way to solve the original problem.

---

<div class="post-metadata">

**Author:** ![anon419083](https://avatars.discourse-cdn.com/v4/letter/a/53a042/32.png) [@anon419083](https://swi-prolog.discourse.group/u/anon419083)\
**Post date:** [June 28, 2023, 1:30pm UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/8 "2023-06-28T13:30:06Z")

</div>

It’s my fault, I admit. But a) the phrasing was somewhat ambiguous and b) one shouldn’t underestimate the positive side: there were a couple of things I wanted to ask about XPCE, but I found a way to tackle them without asking … I hope it is appreciated 🙂

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [June 30, 2023, 9:17am UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/9 "2023-06-30T09:17:36Z")

</div>

> [@mars](#):
>
> According to my current understanding, s(CASP) fits my use case best. So I’m still looking for a way to solve the original problem.

What makes you think so? s(CASP) is (roughly) plain Horn clauses with inequality constraints and basic numeric constraints. It handles negation using stable model semantics, which implies that it finds (possibly) multiple “models” that are consistent with the data (program). It’s combination of negation as failure and classical negation allows it to express 5 levels of certainty. It can provide an justification for its answers.

That all sounds great, but as usual, there are some "but"s. The scalability is poor. In part that is due to the current implementation, but in part it is more fundamental. It deals with negation as _constructive negation_, i.e., `not p(X)` finds all X for which we cannot proof p(X) is true. This easily blows up the computation. In my experience it can be really hard to express really simple things. Your case is an example. This is easily written down in Prolog, but I do not know the s(CASP) solution. That may of course well be due to my lack of experience 🙂

---

<div class="post-metadata">

**Author:** ![oskardrums](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/oskardrums/32/3594_2.png) [@oskardrums](https://swi-prolog.discourse.group/u/oskardrums)\
**Post date:** [June 30, 2023, 7:17pm UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/10 "2023-06-30T19:17:14Z")

</div>

> [@mars](#):
>
> I want that everything has every size until it is stated to have a specific size. Then, it should have this size and no other.

FWIW that sounds like a case that can leverage abduction, e.g.:

```prolog
:- module(foobar, [big_enough/1]).

:- use_module(library(scasp)).

:- abducible maybe_has_size(X, S).

big_enough(X) :- size(X, S), S #>= 2.

size(X, S) :- has_size(X, S).
size(X, S) :- not has_size(X), maybe_has_size(X, S).

has_size(X) :- has_size(X, _).

has_size(b, 1).
has_size(c, 3).

```

Now we can ask:

```prolog
?- module(foobar).
true.

?- ? big_enough(a). % unspecified size
% s(CASP) model
{ big_enough(a), not has_size(a,_), maybe_has_size(a,_A),
  not has_size(a), maybe_has_size(_,_), size(a,_A)
},
{_A>=2} ;
false.

?- ? big_enough(b). % specified size, not big enough
false.

?- ? big_enough(c). % specified size, big enough
% s(CASP) model
{ big_enough(c), maybe_has_size(_,_),
  has_size(c,3), size(c,3)
} ;
false.

```

---

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [June 30, 2023, 8:04pm UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/11 "2023-06-30T20:04:53Z")

</div>

> [@mars](#):
>
> “What sizes of cars are allowed on this road?”

You were initially talking about going off into _infinity_, i.e. anything \> 2. If you’re now talking about e.g. 5 sizes (classifications), that’s far easier to manage and reason about.

Are there other relevant classifications? E.g. number of car doors, emissions level, fuel type, crash safety rating.

For reasoning, such _classifications_ are very convenient 😀

---

<div class="post-metadata">

**Author:** ![mars](https://avatars.discourse-cdn.com/v4/letter/m/e56c9b/32.png) [@mars](https://swi-prolog.discourse.group/u/mars)\
**Post date:** [July 20, 2023, 11:54am UTC](https://swi-prolog.discourse.group/t/making-a-predicate-true-as-default-and-functional/6657/12 "2023-07-20T11:54:02Z")

</div>

Thank you, I think this is what I was looking for!

Do I understand correctly that `:- abducible maybe_has_size(X, S). ` is a shorthand for the following even loop?

```prolog
maybe_has_size(X,S) :- not other_world.
other_world :- not maybe_has_size(X,S).

```

So we have either `maybe_has_size(X, S)`, hence `maybe_has_size(X, S)` is true for every value of `X` and `S` or `not maybe_has_size(X, S)`, hence we do not know about any values of `X` and `S` where `maybe_has_size(X, S)` is true?
