prologswi-prolog# In SWI-Prolog, how can I find a solution that maximises or minimises some atom?

I'm interested in using Prolog to find a solution that maximises some atom of output. Say, for example, there are 10 predicates:

```
solution(1).
solution(2).
solution(3).
solution(4).
solution(5).
solution(6).
```

Finding the solution with the max argument, the usual way, would involve the predicate `findall`

or `setof`

. The problem with that approach is that it uses a lot of RAM. What I would be interested in instead is something like:

```
findmin(MinAtom, Solution, (predicate(MinAtom, Solution))).
```

This way, the graph search would not need to use a tonne of memory storing all execution paths, and could instead permute through each execution path, only retaining the running *minimum* solution along the way. Is there a native way of doing this?

I thought of a way to 'shimmy' this sort of behaviour into place, by first taking an arbitrary solution, then finding a solution that does better, and then continuing this process until no *better* solution is found, at which point the program halts. However, this approach involves some execution duplication while Prolog performs the graph search.

Anyone any insights on how to address this sort of problem in Prolog? It relates somewhat to integer linear programming, but does ILP in the graph search way instead.

I would also be amenable to hacky approaches, e.g. abusing the `fail`

predicate.

Solution

Unless there is a subtlety in your question I am missing:

```
?- aggregate_all(min(X), solution(X), Min).
Min = 1.
?- aggregate_all(max(X), solution(X), Max).
Max = 6.
```

Unless you break it, this will run in constant memory. Please check the implementation, it is interesting. It shows how you can use Prolog as one of the more basic programming languages.

Is there a native way of doing this?

There is a probably non-portable (across Prolog implementations) way. In the case of SWI-Prolog, the basic idea can be seen in the source code of the library. For max():

```
aggregate_all(max(X), Goal, Max) :-
!,
State = state(X),
( call(Goal),
arg(1, State, M0),
M is max(M0,X),
nb_setarg(1, State, M),
fail
; arg(1, State, Max),
nonvar(Max)
).
```

The relevant non-portable predicate is nb_setarg/3. Another annoying limitation is that each "template" is hardcoded, I assume for efficiency. So while you can define your own aggregator, this will take you to back to bagof/findall land, with the current library implementation. You need to hardcode your own "loop" like the library does for the predefined aggregators.

- Turbo Prolog: Create a palindrome by adding the smallest number of characters to the list
- Prolog order of clause body gives different results when using negation
- Problem With a Predicate to Check if X Occurs Exactly Four Times in a List
- Most General Unifier (Prolog)
- In prolog, functors vs predicates, and goals
- Solving N-queens with Constraint Handling Rules
- 'if' in prolog?
- Are there any Prolog compilers that can optimize by targeting specific queries?
- gprolog: Getting a stacktrace after an exception
- Efficient solution for the same-fringe problem for binary trees
- Understanding prolog \+ and the engine's solution space search
- Prolog, X element before element Y on list
- What is the difference between once and cut in prolog?
- Getting the seed set by the ECLiPSe on loading
- Get simple Prolog example to work
- How to do recursion in a L-system inspired rewrite System, without DCG
- Maximum number of atoms in SICStus Prolog 4
- How to create a list dynamically in Prolog?
- Prolog Syntax for Dependent Conditions
- Guard clauses in prolog?
- phrase_from_stream/2 nontermination (Stream from http_open/3)
- SWI-Prolog: [FATAL ERROR: Could not find system resources]
- DCG LaTeX printer for FOL prover
- Prolog: a person is a sibling of himself?
- When can I safely avoid storing temporary calculations in Prolog?
- Prolog - Solution of a riddle
- Is the structure of my Prolog expression isomorphic to the structure of the Liar Paradox?
- Syntax error: Operator expected in Prolog
- Assertion Failure in SWI-Prolog When Using pyswip to Consult a Prolog File
- Retract by partial match?