View source with raw comments or as raw
    1:- module(scasp_json,
    2          [ scasp_results_json/2        % +Results, -Dict
    3          ]).    4:- use_module(output).    5:- use_module(options).    6:- use_module(clp/disequality).    7:- use_module(clp/clpq).    8:- use_module(source_ref).

s(CASP) JSON I/O

*/

 scasp_results_json(+Results, -Dict) is det
Generate a JSON document from the results of the s(CASP) solver. Results is a dict holding:
query
The query represented as a list or as a conjunction.
answers
A list of answers. Each answer is a dict holding the keys below. This dict is normally created using scasp_solve/4.
query
answer
Nth answer (1, 2, ...)
bindings
model
tree
The justification tree. Optional.
time
inputs
Description of the input. Typically a list of file names. Optional.
cpu
COU time used to get all answers (optional).
   38:- det(scasp_results_json/2).   39scasp_results_json(Result, Dict) :-
   40    _{ query: Query,
   41       answers: Answers
   42     } :< Result,
   43    Dict0 = scasp_result{ solver: Version,
   44                          query: JQuery,
   45                          answers: JAnswers
   46                       },
   47    scasp_version(Version),
   48    query_json(Query, JQuery),
   49    maplist(answer_json, Answers, JAnswers),
   50    copy_dict_slots([cpu-time, inputs], Dict0, Dict).
   51
   52copy_dict_slots(Slots, Dict0, Dict) :-
   53    foldl(copy_dict_slot, Slots, Dict0, Dict).
   54
   55copy_dict_slot(Name, Dict0, Dict), atom(Name) =>
   56    (   Value = Dict0.get(Name)
   57    ->  Dict = Dict0.put(Name, Value)
   58    ;   Dict0 = Dict
   59    ).
   60copy_dict_slot(Name-To, Dict0, Dict) =>
   61    (   Value = Dict0.get(Name)
   62    ->  Dict = Dict0.put(To, Value)
   63    ;   Dict0 = Dict
   64    ).
   65
   66
   67:- meta_predicate query_json(:, -).   68:- det(query_json/2).   69query_json(_:Query, JQuery), is_list(Query) =>
   70    delete(Query, o_nmr_check, Query1),
   71    delete(Query1, true, Query2),
   72    plain_term_json(Query2, JQuery).
   73query_json(_:Query, JQuery) =>
   74    comma_list(Query, List),
   75    plain_term_json(List, JQuery).
 answer_json(+Answer, -Dict) is det
   79:- det(answer_json/2).   80answer_json(Answer, Dict),
   81    _{ answer:Counter,
   82       bindings:Bindings,
   83       model:Model,
   84       tree:_:Tree,
   85       time:Time
   86     } :< Answer =>
   87    Dict = scasp_answer{answer: Counter,
   88                        time: Time.cpu,
   89                        bindings: JBindings,
   90                        model: JModel,
   91                        tree: JTree,
   92                        constraints: Constraints},
   93    maplist(binding_json, Bindings, Pairs),
   94    dict_create(JBindings, #, Pairs),
   95    maplist(model_term_json, Model, JModel),
   96    tree_json(Tree, JTree),
   97    constraints_json(t(Bindings,Model,JTree), Constraints).
   98answer_json(Answer, Dict),
   99    _{ answer:Counter,
  100       bindings:Bindings,
  101       model:Model,
  102       time:Time
  103     } :< Answer =>
  104    Dict = scasp_answer{answer: Counter,
  105                        time: Time.cpu,
  106                        bindings: JBindings,
  107                        model: JModel,
  108                        constraints: Constraints},
  109    maplist(binding_json, Bindings, Pairs),
  110    dict_create(JBindings, #, Pairs),
  111    maplist(model_term_json, Model, JModel),
  112    constraints_json(t(Bindings,Model), Constraints).
  113
  114binding_json(Name=Value, Name-JValue) :-
  115    model_term_json(Value, JValue).
  116
  117tree_json(Root-Children, Dict) =>
  118    Dict = #{ node: JRoot,
  119              children: JChildren },
  120    node_json(Root, JRoot),
  121    maplist(tree_json, Children, JChildren).
  122
  123node_json(chs(Node), Dict) =>
  124    model_term_json(Node, Dict0),
  125    Dict = Dict0.put(chs, true).
  126node_json(assume(Node), Dict) =>
  127    model_term_json(Node, Dict0),
  128    Dict = Dict0.put(assume, true).
  129node_json(proved(Node), Dict) =>
  130    model_term_json(Node, Dict0),
  131    Dict = Dict0.put(proved, true).
  132node_json(abduced(Node), Dict) =>
  133    model_term_json(Node, Dict0),
  134    Dict = Dict0.put(abduced, true).
  135node_json(goal_origin(Node, Origin), Dict) =>
  136    scasp_source_reference_file_line(Origin, File, Line),
  137    node_json(Node, Dict0),
  138    Dict1 = Dict0.put(source_file, File),
  139    Dict  = Dict1.put(source_line, Line).
  140node_json(Node, Dict) =>
  141    model_term_json(Node, Dict).
 model_term_json(+ModelTerm, -Dict) is det
  146:- det(model_term_json/2).  147model_term_json(not(-Term), Dict) =>
  148    Dict = scasp_model_term{truth: likely,   value: TermJSON},
  149    module_term_json(Term, TermJSON).
  150model_term_json(-Term, Dict) =>
  151    Dict = scasp_model_term{truth: false,    value: TermJSON},
  152    module_term_json(Term, TermJSON).
  153model_term_json(not(Term), Dict) =>
  154    Dict = scasp_model_term{truth: unlikely, value: TermJSON},
  155    module_term_json(Term, TermJSON).
  156model_term_json(Term, Dict) =>
  157    Dict = scasp_model_term{truth: true,     value: TermJSON},
  158    module_term_json(Term, TermJSON).
  159
  160module_term_json(M:Term, Dict) =>
  161    plain_term_json(Term, Dict0),
  162    Dict = Dict0.put(module, M).
  163module_term_json(Term, Dict) =>
  164    plain_term_json(Term, Dict).
 plain_term_json(+Term, -Dict) is det
  168:- det(plain_term_json/2).  169plain_term_json(Var, Dict), var(Var) =>
  170    (   ovar_var_name(Var, Name)
  171    ->  Dict = prolog{type: var,
  172                      name: Name}
  173    ;   ovar_is_singleton(Var)
  174    ->  Dict = prolog{type: var}
  175    ).
  176plain_term_json(Var, Dict), var_number(Var, Num) =>
  177    (   Num == '_'
  178    ->  Dict = prolog{type: var}
  179    ;   format(string(S), '~p', [Var]),
  180        Dict = prolog{type: var,
  181                      name: S}
  182    ).
  183plain_term_json(Atom, Dict), atom(Atom) =>
  184    Dict = atom{type:atom, value:Atom}.
  185plain_term_json(Num, Dict), rational(Num, N, D) =>
  186    (   current_prolog_flag(scasp_real, Decimals),
  187        (   integer(Decimals)
  188        ->  truncate(Num, Decimals, Value)
  189        ;   Decimals == float
  190        ->  Value is float(Num)
  191        )
  192    ->  Dict = prolog{type:number, value:Value}
  193    ;   Dict = prolog{type:rational, numerator:N, denominator:D}
  194    ).
  195plain_term_json(Num, Dict), number(Num) =>
  196    Dict = prolog{type:number, value:Num}.
  197plain_term_json(List, JList), is_list(List) =>
  198    maplist(plain_term_json, List, JList).
  199plain_term_json(Compound, Dict), compound(Compound) =>
  200    compound_name_arguments(Compound, Name, Arguments),
  201    Dict = prolog{type:compound, functor:Name, args:JArgs},
  202    maplist(plain_term_json, Arguments, JArgs).
  203
  204truncate(Rat, Decimals, Value) :-
  205    Z is Rat * 10**Decimals,
  206    ZA is truncate(Z),
  207    Value is float(ZA / 10**Decimals).
 constraints_json(+Term, -Dict) is det
  211:- det(constraints_json/2).  212constraints_json(Term, Dict) :-
  213    term_attvars(Term, Attvars),
  214    include(has_constraints, Attvars, CVars),
  215    copy_term(CVars, Copy),
  216    inline_constraints(Copy, []),
  217    maplist(constraint_json, Copy, Constraints),
  218    dict_create(Dict, #, Constraints).
  219
  220has_constraints(Var) :-
  221    get_neg_var(Var, _List),
  222    !.
  223has_constraints(Var) :-
  224    is_clpq_var(Var).
  225
  226constraint_json('| '(Var, {'\u2209'(Var, List)}), Pair) =>
  227    Pair = Name-constraint{ type: not_in, set: JList},
  228    var_name(Var, Name),
  229    maplist(plain_term_json, List, JList).
  230constraint_json('| '(Var, {Term}), Pair) =>
  231    Pair = Name-constraint{ type: clpq, constraints: Constraints},
  232    var_name(Var, Name),
  233    comma_list(Term, Constraints0),
  234    maplist(clpq_json(Var), Constraints0, Constraints).
  235
  236var_name('$VAR'(Name0), Name) =>
  237    Name = Name0.
  238var_name(Var, Name), ovar_var_name(Var, Name0) =>
  239    Name = Name0.
  240
  241clpq_json(Var, Term, Dict), Term =.. [Op, Var, Arg] =>
  242    Dict = constraint{type:  Op, value: JArg},
  243    plain_term_json(Arg, JArg).
  244
  245
  246:- multifile
  247    json:json_dict_pairs/2.  248
  249json:json_dict_pairs(Dict, Pairs) :-
  250    is_dict(Dict, Tag),
  251    order(Tag, Order),
  252    dict_keys(Dict, All),
  253    sort(Order, Ordered),
  254    ord_subtract(All, Ordered, Unordered),
  255    phrase(json_pairs(Order, Dict), Pairs, Pairs1),
  256    phrase(json_pairs(Unordered, Dict), Pairs1).
  257
  258json_pairs([], _) -->
  259    [].
  260json_pairs([H|T], Dict) -->
  261    (   {get_dict(H, Dict, Value)}
  262    ->  [H-Value]
  263    ;   []
  264    ),
  265    json_pairs(T, Dict).
  266
  267order(scasp_result,     [solver,inputs,query,time,answers]).
  268order(scasp_answer,     [answer,time,bindings,model,tree]).
  269order(scasp_model_term, [truth, value, chs, assume, proved]).
  270order(prolog,           [type,functor,numerator,denominator,name,value]).
  271order(constraint,       [type,set,constraints,value])