View source with raw comments or as raw
    1/*  Part of sCASP
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        jan@swi-prolog.org
    5    Copyright (c)  2021, SWI-Prolog Solutions b.v.
    6    All rights reserved.
    7
    8    Redistribution and use in source and binary forms, with or without
    9    modification, are permitted provided that the following conditions
   10    are met:
   11
   12    1. Redistributions of source code must retain the above copyright
   13       notice, this list of conditions and the following disclaimer.
   14
   15    2. Redistributions in binary form must reproduce the above copyright
   16       notice, this list of conditions and the following disclaimer in
   17       the documentation and/or other materials provided with the
   18       distribution.
   19
   20    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   21    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   22    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   23    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   24    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   25    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   26    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   27    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   28    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   30    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31    POSSIBILITY OF SUCH DAMAGE.
   32*/
   33
   34:- module(scasp_model,
   35          [ canonical_model/2,          % +RawModel, -Canonical
   36            unqualify_model/3,          % +ModelIn, +Module, -ModelOut
   37            print_model/2               % :Model, +Options
   38          ]).   39:- use_module(library(apply)).   40:- use_module(library(lists)).   41:- use_module(library(pairs)).   42
   43:- use_module(common).   44:- use_module(modules).   45:- use_module(output).   46
   47:- meta_predicate
   48    canonical_model(:, -),
   49    print_model(:, +).   50
   51:- multifile
   52    model_hook/2.

sCASP model handling

*/

 canonical_model(:RawModel, -Canonical)
   61canonical_model(M:Model, CanModel) :-
   62    flatten(Model, FlatModel),
   63    exclude(nonmodel_term, FlatModel, Model1),
   64    sort(Model1, Unique),
   65    maplist(raise_negation, Unique, Raised),
   66    filter_shown(M, Raised, Filtered),
   67    sort_model(Filtered, Sorted),
   68    simplify_model(Sorted, CanModel).
   69
   70nonmodel_term(abducible(_)).
   71nonmodel_term(proved(_)).
   72nonmodel_term(chs(_)).
   73nonmodel_term(o_nmr_check).
   74nonmodel_term(not(X)) :-
   75    nonvar(X),
   76    !,
   77    nonmodel_term(X).
   78nonmodel_term(Term) :-
   79    functor(Term, Name, _),
   80    (   sub_atom(Name, 0, _, _, 'o_')
   81    ->  true
   82    ;   sub_atom(Name, _, _, 0, '$')
   83    ).
 filter_shown(+Module, +Model, -Shown) is det
Handle the show/1 directives. All terms are shown for a target module if pr_show_predicate/1 is not defined for that module. Otherwise the terms associated with the module are filtered using pr_show_predicate/1.
   92filter_shown(M, Model, Shown) :-
   93    maplist(tag_module(M), Model, Tagged),
   94    maplist(arg(1), Tagged, Modules),
   95    sort(Modules, Unique),
   96    include(has_shown, Unique, Filter),
   97    (   Filter == []
   98    ->  Shown = Model
   99    ;   convlist(do_show(Filter), Tagged, Shown)
  100    ).
  101
  102tag_module(M, Term, t(Q, Unqualified, Term)) :-
  103    model_term_module(M:Term, Q),
  104    unqualify_model_term(Q, Term, Unqualified).
  105
  106has_shown(Module) :-
  107    clause(Module:pr_show_predicate(_), _),
  108    !.
  109
  110do_show(Filter, t(M,Unqualified,Term), Term) :-
  111    (   memberchk(M, Filter)
  112    ->  M:pr_show_predicate(Unqualified)
  113    ;   true
  114    ).
 sort_model(+ModelIn, -Sorted) is det
Sort the model by literal, getting affirming and denying knowledge about a literal together. If multiple terms about the same literal appear they are ordered:
  1. positive
  2. not(positive)
  3. -positive
  4. not(-positive).
  127sort_model(ModelIn, Sorted) :-
  128    map_list_to_pairs(literal_key, ModelIn, Pairs),
  129    keysort(Pairs, KSorted),
  130    pairs_values(KSorted, Sorted).
  131
  132literal_key(Term, Literal-Flags) :-
  133    literal_key(Term, Literal, 0, Flags).
  134
  135literal_key(not(X), Key, F0, F) =>
  136    literal_key(X, Key, F0, F1),
  137    F is F1+0x1.
  138literal_key(-(X), Key, F0, F) =>
  139    literal_key(X, Key, F0, F1),
  140    F is F1+0x2.
  141literal_key(X, Key, F0, F) =>
  142    Key = X,
  143    F = F0.
 simplify_model(+ModelIn, -ModelOut) is det
Remove model terms that are entailed by other model terms.
  149simplify_model([not(X0),-X1|T0], M), X0 == X1 =>
  150    M = [-X1|M0],
  151    simplify_model(T0, M0).
  152simplify_model([X0, not(-(X1))|T0], M), X0 == X1 =>
  153    M = [X0|M0],
  154    simplify_model(T0, M0).
  155simplify_model([H|T0], M) =>
  156    M = [H|M0],
  157    simplify_model(T0, M0).
  158simplify_model([], M) =>
  159    M = [].
 unqualify_model(+ModelIn, +Module, -ModelOut) is det
Restore the model relation to modules.
  165unqualify_model(Model0, Module, Model) :-
  166    maplist(unqualify_model_term(Module), Model0, Model).
 print_model(:Model, +Options) is det
Print the model in aligned columns. Options processed:
width(Width)
Assumed terminal width. Default from tty_size/2 or 80.

Model terms are printed in columns. E.g., for a 10 atom model and 4 columns we get:

   1  4  7  10
   2  5  8
   3  6  9
  184print_model(Model, Options) :-
  185    model_hook(Model, Options),
  186    !.
  187print_model(_:Model, Options) :-
  188    (   option(width(Width), Options)
  189    ->  true
  190    ;   catch(tty_size(_, Width), _, Width = 80)
  191    ),
  192    layout(Model, Width, Layout),
  193    compound_name_arguments(Array, v, Model),
  194    format('{ ', []),
  195    print_table(0, Array, Layout.put(_{ sep:',',
  196                                        end:'\n}',
  197                                        prefix:'  ',
  198                                        options:Options
  199                                      })).
  200
  201print_table(I, Array, Layout) :-
  202    Cols = Layout.cols,
  203    Rows = Layout.rows,
  204    Row is I // Cols,
  205    Col is I mod Cols,
  206    Index is Row + Col * Rows + 1,
  207
  208    % If the next index is outside, we need a newline.  If we are
  209    % also on the last row we have the very last element
  210    (   NIndex is Row + (Col+1) * Rows + 1,
  211        functor(Array, _, LastIndex),
  212        NIndex =< LastIndex
  213    ->  NL = false,
  214        Last = false
  215    ;   NL = true,
  216        (   Row+1 =:= Rows
  217        ->  Last = true
  218        ;   Last = false
  219        )
  220    ),
  221
  222    % If we are not the last on the line and not the last, print the
  223    % cell, padding to the column with and followed by a separator (,)
  224    % Else we print withput padding either a separator or the end.
  225    (   arg(Index, Array, Atom)
  226    ->  (   NL == false,
  227            Last == false
  228        ->  format('~|~@~w~t~*+',
  229                   [print_model_term(Atom, Layout.options),
  230                    Layout.sep, Layout.col_width])
  231        ;   Last == false
  232        ->  format('~@~w', [print_model_term(Atom, Layout.options), Layout.sep])
  233        ;   format('~@~w', [print_model_term(Atom, Layout.options), Layout.end])
  234        ),
  235        Print = true
  236    ;   true
  237    ),
  238
  239    % Emit a newline if this is the last one on the line and we printed this
  240    % cell.
  241    (   Last == true
  242    ->  true
  243    ;   (   Print == true, NL == true
  244        ->  format('~n~w', [Layout.prefix])
  245        ;   true
  246        ),
  247        I2 is I+1,
  248        print_table(I2, Array, Layout)
  249    ).
  250
  251layout(Atoms, Width, _{cols:Cols, rows:Rows, col_width:ColWidth}) :-
  252    length(Atoms, L),
  253    longest(Atoms, Longest),
  254    Cols0 is max(1, Width // (Longest + 3)),
  255    Rows is ceiling(L / Cols0),
  256    Cols is ceiling(L/Rows),
  257    ColWidth is min(Longest+3, Width // Cols).
  258
  259longest(List, Longest) :-
  260    longest(List, 0, Longest).
  261
  262longest([], M, M) :- !.
  263longest([H|T], Sofar, M) :-
  264    write_length(H, Length,
  265                 [ portray(true),
  266                   numbervars(true),
  267                   quoted(true)
  268                 ]),
  269    Length >= Sofar,
  270    !,
  271    longest(T, Length, M).
  272longest([_|T], S, M) :-
  273    longest(T, S, M)