------------------------------------------------------------------------
--                 An example of visual expert system.                --
--               The program is written on Actor Prolog.              --
--               (c) Alexei A. Morozov, March 19, 1999.               --
------------------------------------------------------------------------
-- This is my favorite program. It helps to cook black rowan, apple,  --
-- and strawberry jam. Actually I wrote this program to train myself  --
-- in carrying out SADT interview. For that I have asked my mother    --
-- to tell me how one should cook a jam. I made an effort to draw     --
-- the model as detailed as possible; thus the interview has          --
-- lengthened about two days. The result was unexpected for both of   --
-- us. My mother was very surprised when I have showed her the total  --
-- list of cooking battery that she usually uses for cooking ordinary --
-- jam. Besides I have learned to cook a little.                      --
-- Mother, thank you for the help!                                    --
------------------------------------------------------------------------
-- A logical description of the blocks of the SADT model.             --
------------------------------------------------------------------------
-- This class is simply a dummy. It opens a dialog box for            --
-- choosing berries and fruits.                                       --
------------------------------------------------------------------------
class 'CHOOSE_BERRIES_AND_FRUITS' specializing 'DIALOG':
value_o1;
identifier= "ChooseFruits";
[
]
------------------------------------------------------------------------
-- The following classes correspond to blocks of the SADT model.      --
-- The main purpose of these classes is keeping lists of cooking      --
-- battery corresponding to various blocks of the SADT model.         --
-- In addition to this purpose some blocks implement the following    --
-- functions:                                                         --
-- 1) They transmit some values (names of selected berries and        --
--    fruits) from an input to the outputs of block.                  --
-- 2) They check if selected berries and fruits are conformed to      --
--    given block. If they do not conform, then the execution of the  --
--    'goal' actor is terminated with failure and the process changes --
--    its state to "failed". In this case the color of corresponding  --
--    block on the screen becomes red.                                --
-- 3) They calculate suggested period of the heat of sugar mixture    --
--    for selected berries and fruits.                                --
-- The classes corresponding to compound blocks are descendants of    --
-- the 'Compound_Block' class. The destination of this class we will  --
-- discuss later in the course of consideration of the "Analysis of   --
-- model" block.                                                      --
------------------------------------------------------------------------
class 'WASH_UP_JARS_AND_LIDS' specializing 'Simple_Block':
[
]
------------------------------------------------------------------------
class 'BOIL_SOME_WATER_IN_A_KETTLE' specializing 'Simple_Block':
[
instrument()= "A kettle".
]
------------------------------------------------------------------------
class 'CLEANSE_LIDS_BY_BOILING_WATER' specializing 'Simple_Block':
[
instrument()= "A saucepan for boiling water".
]
------------------------------------------------------------------------
class 'CLEANSE_JAM-JARS_BY_BOILED_WATER' specializing 'Simple_Block':
[
instrument()= "A kettle".
]
------------------------------------------------------------------------
class 'DRY_JAM-JARS_AND_LIDS' specializing 'Simple_Block':
[
]
------------------------------------------------------------------------
class 'WASH_BERRIES_AND_FRUITS' specializing 'Simple_Block':
value_i1;
protecting: value_o1;
[
goal:-!,
        value_o1 == value_i1.
--
instrument()= "A colander".
]
------------------------------------------------------------------------
class 'PREPARE_SOME_MIXTURE_OF_HARD_BERRIES_AND_SUGAR'
specializing 'Compound_Block':
value_i1;
[
goal:-!,
        check_fruits(value_i1).
--
check_fruits("Black rowan").
]
------------------------------------------------------------------------
class 'PREPARE_SOME_MIXTURE_OF_LARGE_FRUITS_AND_SUGAR'
specializing 'Compound_Block':
value_i1;
[
goal:-!,
        check_fruits(value_i1).
--
check_fruits("The \"Antonovka\" apples").
]
------------------------------------------------------------------------
class 'PREPARE_SOME_MIXTURE_OF_SOFT_BERRIES_AND_SUGAR'
specializing 'Compound_Block':
value_i1;
[
goal:-!,
        check_fruits(value_i1).
--
check_fruits("Strawberry").
]
------------------------------------------------------------------------
class 'BOIL_SOME_WATER_IN_THE_SAUCEPAN' specializing 'Simple_Block':
[
instrument()= "A saucepan for boiling water".
]
------------------------------------------------------------------------
class 'PREPARE_SOME_SYRUP' specializing 'Simple_Block':
value_i1;
value_o1;
[
goal:-!,
        value_o1 == value_i1.
--
instrument()= "A saucepan or copper basin".
instrument()= "Wooden spoon".
]
------------------------------------------------------------------------
class 'BLANCH_BERRIES' specializing 'Simple_Block':
value_i2;
value_o1;
[
goal:-!,
        value_o1 == value_i2.
--
instrument()= "A colander".
instrument()= "A saucepan for boiling water".
]
------------------------------------------------------------------------
class 'PUT_BERRIES_IN_SYRUP' specializing 'Simple_Block':
value_i1;
value_o1;
[
goal:-!,
        value_o1 == value_i1.
--
instrument()= "A saucepan or copper basin".
]
------------------------------------------------------------------------
class 'CUT_FRUITS_INTO_LOBULES' specializing 'Simple_Block':
value_i1;
value_o1;
[
goal:-!,
        value_o1 == value_i1.
--
instrument()= "A knife of stainless steel".
]
------------------------------------------------------------------------
class 'SPRINKLE_WITH_SUGAR' specializing 'Simple_Block':
value_i1;
value_o1;
[
goal:-!,
        value_o1 == value_i1.
--
instrument()= "A saucepan or copper basin".
]
------------------------------------------------------------------------
class 'SUSPEND_THE_PROCESS_FOR_6-8_HOURS' specializing 'Simple_Block':
value_i1;
value_o1;
[
goal:-!,
        value_o1 == value_i1.
--
instrument()= "A saucepan or copper basin".
]
------------------------------------------------------------------------
class 'ADD_SOME_WATER_IN_THE_MIXTURE' specializing 'Simple_Block':
value_i1;
value_o1;
[
goal:-!,
        value_o1 == value_i1.
--
instrument()= "A saucepan or copper basin".
]
------------------------------------------------------------------------
class 'BOILING_CYCLE_FOR_HARD_BERRIES_AND_FRUITS'
specializing 'Compound_Block':
value_i1;
[
goal:-!,
        check_fruits(value_i1).
--
check_fruits("Black rowan").
check_fruits("The \"Antonovka\" apples").
]
------------------------------------------------------------------------
class 'BOILING_CYCLE_FOR_SOFT_BERRIES_AND_FRUITS'
specializing 'Compound_Block':
value_i1;
[
goal:-!,
        check_fruits(value_i1).
--
check_fruits("Strawberry").
]
------------------------------------------------------------------------
class 'HEAT_THE_MIXTURE' specializing 'DIALOG':
value_i2;
time;
identifier      = "HeatUpMixture";
fruits          = value_i2;
[
goal:-!,
        set_time(value_i2,time).
--
set_time(#,"3-5"):-!.
set_time("Black rowan","3"):-!.
set_time("The \"Antonovka\" apples",5):-!.
set_time("Strawberry","---"):-!.
set_time(_,"3-5"):-!.
--
instrument()= "A saucepan or copper basin".
instrument()= "Wooden spoon".
]
------------------------------------------------------------------------
class 'SUSPEND_THE_PROCESS' specializing 'Simple_Block':
[
instrument()= "A saucepan or copper basin".
]
------------------------------------------------------------------------
class 'CHECK_IF_JAM_IS_READY' specializing 'Simple_Block':
[
instrument()= "Wooden spoon".
instrument()= "A saucer".
]
------------------------------------------------------------------------
class 'MAIN_PHASE_OF_BOILING' specializing 'DIALOG':
value_i1;
time;
identifier      = "HeatUpMixture";
fruits          = value_i1;
[
goal:-!,
        set_time(value_i1,time).
--
set_time(#,"---"):-!.
set_time("Strawberry","10"):-!.
set_time(_,"---"):-!.
--
instrument()= "A saucepan or copper basin".
instrument()= "Wooden spoon".
]
------------------------------------------------------------------------
class 'SUPPLEMENTARY_PHASE_OF_BOILING' specializing 'Simple_Block':
[
instrument()= "A saucepan or copper basin".
instrument()= "Wooden spoon".
]
------------------------------------------------------------------------
class 'COOL_JAM' specializing 'Simple_Block':
[
instrument()= "A saucepan or copper basin".
]
------------------------------------------------------------------------
class 'POUR_JAM_INTO_JARS' specializing 'Simple_Block':
[
instrument()= "Wooden spoon".
instrument()= "Canning equipment".
]
------------------------------------------------------------------------
class 'Simple_Block':
[
goal.
--
show(_).
]
------------------------------------------------------------------------
-- This block creates and demonstrates total list of cooking battery  --
-- necessary for jam-making with chose berries and fruits.            --
-- This block implements the following idea:                          --
-- 1) The values of the "container" slots are created automatically   --
--    during the translation of the SADT diagrams. This slot contains --
--    a process corresponding to the block that contains the given    --
--    block. It is the "JAM-MAKING" block. A special resident proves  --
--    the 'instrument' predicate in this block.                       --
-- 2) The "JAM-MAKING" block as well as other compound blocks are     --
--    implemented on the basis of the 'Compound_Block' class in the   --
--    course of translation of the SADT model. The 'Compound_Block'   --
--    class is an ancestor of corresponding classes.                  --
-- 3) The 'Compound_Block' class is defined in the text of the        --
--    program. At the same time there is the 'instrument' function    --
--    that must be defined in the 'Compound_Block' class. The result  --
--    calculated by this function is a result of the 'component'      --
--    function.                                                       --
-- 4) The 'component' function is non-deterministic one. It is        --
--    defined automatically during the translation of compound        --
--    blocks. The results calculated by this function are processes   --
--    that correspond to the blocks that are internal components of   --
--    given compound block.                                           --
-- 5) Thus the "Analysis of model" block gets a list of processes     --
--    corresponding to the neighboring blocks with the help of a      --
--    resident.                                                       --
-- 6) Obtained list is transmitted to other resident in the recursive --
--    definition of the process 'Instruments'. This process proves    --
--    the same 'instrument' predicate in these worlds.                --
-- 7) In the case if the 'instrument' predicate is proven in a simple --
--    block, the corresponding process returns a list of cooking      --
--    battery related to given block. In the case if the predicate is --
--    proven in a compound block, the execution of the predicate      --
--    occurs to be the same as in the "JAM-MAKING" block considered   --
--    above. Thus the resident computes a list containing cooking     --
--    battery as like as processes corresponding to some internal     --
--    blocks.                                                         --
-- 8) Created list is transmitted to the next level of recursion and  --
--    processed by the next resident. This recursive processing       --
--    continues till the list is not refined on the given stage of    --
--    recursion. If the input list is equal to the output list on     --
--    given stage of recursion, then the examination of the tree of   --
--    blocks has reached all the leafs of the tree. In this case      --
--    there are no more processes in the list of cooking battery.     --
-- 9) Processed list of cooking battery is sorted and demonstrated    --
--    in the dialog box.                                              --
------------------------------------------------------------------------
class 'ANALYSIS_OF_MODEL:_WHAT_KITCHEN_UTENSILS_ARE_WE_NEED?'
specializing 'DIALOG':
--
identifier= "ListOfInstruments";
--
title;
name;
number;
model;
x;
y;
text_color;
container;
con;
--
result;
instruments;
--
agent   = (('FindInstruments',
                        container,
                        protecting: result));
[
goal:-
        refine_list(result,[],instruments),!.
goal:-!,
        [result].
--
refine_list([],List,List):-!.
refine_list([#|Rest],List1,List2):-!,
        refine_list(Rest,List1,List2).
refine_list([Item|Rest],List1,List3):-
        is_list(Item),!,
        refine_list(Item,List1,List2),
        refine_list(Rest,List2,List3).
refine_list([Item|Rest],List1,List2):-
        is_not_element(Item,List1),!,
        refine_list(Rest,[Item|List1],List2).
refine_list([_|Rest],List1,List2):-!,
        refine_list(Rest,List1,List2).
refine_list(_,List,List).
--
is_list([]):-!.
is_list([_|_]).
--
is_not_element(_,[]):-!.
is_not_element(Item,[Item|_]):-!,
        fail.
is_not_element(Item,[_|List]):-
        is_not_element(Item,List).
--
show(_):-
        show.
]

------------------------------------------------------------------------
class 'FindInstruments' specializing 'ALPHA':
container;
result;
agent   = (('Instruments',
                suspending: source_list= [],
                target_list= container,
                protecting: result
                ));

[
goal:-!.
]
------------------------------------------------------------------------
class 'Instruments' specializing 'Alpha':
source_list;
target_list;
result;
--
tail_list;
tail_result;
tail    = (('Instruments',
                suspending: source_list=tail_list,
                target_list=target_list ?? instrument(),
                protecting: result=tail_result
                ));
con     = ('Console');
[
goal:-
        source_list == target_list,!,
        result == target_list.
goal:-
        tail_list== target_list,
        result== tail_result.
]
------------------------------------------------------------------------
class 'Compound_Block' specializing 'Alpha':
c = ('Console');
[
instrument()= Block
        :-!,
        component(Block).
]
------------------------------------------------------------------------