The tutorial logigram ##################### This tutorial shows a typical use of the backtracking cluster. How to compile? =============== Just type: {{{{ se c -boost -clean -o logigram logigram }}}} What does it do? ================ That tutorial that shows how to solve problems sometimes called logigrams. The logigrams are made of a set of items (persons, date, places, ...) grouped into categories and set of true propositions about the items. From these propositions you must deduce how the given items are combined together. Here is an example: That program solves the following classic problem. Knowing that: - the house of the english is red, - the spanish has a dog, - one drink coffee in the green house, - the ukrainian drinks tea, - the green house is just at right of the ivory house, - the man that smokes winstons have a snail, - the man that smokes kools have the yellow house, - one drinks milk in the house at the middle, - the norvegian lives in the house at left, - the one who smokes chesterfields is neibourgh of a fox, - the one who smokes kools is neibourgh of a horse, - the one who smokes luckystrike drinks orange juice, - the japanese smokes parliaments, - the norvegian is neibourgh of the blue house. Tell who got the zebra and who drinks water? The output of the program is {{{{ > logigram +-----------+-------------+--------+--------------+---------------+--------+ | house | nationality | animal | drink | cigarette | color | +-----------+-------------+--------+--------------+---------------+--------+ | left | norvegian | fox | water | kools | yellow | | mid-left | ukrainian | horse | tea | chesterfields | blue | | middle | english | snail | milk | winston | red | | mid-right | spanish | dog | orange juice | luckystrike | ivory | | right | japanese | zebra | coffee | parliaments | green | +-----------+-------------+--------+--------------+---------------+--------+ 1 solution }}}} There are three other problems that let you challenge the tutorial. Exercice: in file logigram.e, feature describe_problem_classic put in comment line that declares that the house of the english is red as below and re-run. How many solutions now? Happy chrismas! {{{{ -- rule(yes(item("nationality", "english"), item("color", "red"))) }}}} Exercice: in file logigram.e, feature describe_problem_classic put line that declares the ordered group house at the end of the groups declarations and measure the difference of computing time with the command 'time' (under unix). Explain. Exercice: write a program that solves the same problem. Exercice: write a program that solves any problem of the same kind. How does it work? ================= It works in three steps: - Creation of the problem description. - Transformation of the description to a AND/OR tree of possible permutations. - Exploration of the AND/OR tree by backtracking to retrieve the solutions. The main idea is to use permutations for retrieving the solutions. Description of the problem -------------------------- The description is managed with an object of the class DESCRIPTION that mainly contains: - a set of groups; - a set of constraints through an object of class CONSTRAINT_SET. First of all, the groups must be declared. There are 3 kind of groups: - the atomic groups; - the ordered groups what means that the order of the items of the group cares and that each item receive a number that is its place, beginning to zero; - the numeric groups that must contain numeric items. The groups are all managed through objects of class GROUP. The constraints (class CONSTRAINT) are distinguished in two types: - Constraints on couples (class CONSTRAINT_COUPLE association of a couple of two items that are not of the same group), that comprises: - positive association of a couple (class CONSTRAINT_YES) what meaning is that the 2 items are associated together (example: marie had 4 children); - negative association of a couple (class CONSTRAINT_NO) what meaning is that the 2 items are never associated together (example: marie didn't have 4 children). - Logical constraints (class CONSTRAINT_LOGICAL) that currently only are the relationnal constraints (class CONSTRAINT_RELATIONAL) on some integer expressions, that comprises equal, greater, lesser, and not equal, from the classes CONSTRAINT_EQUAL, CONSTRAINT_GREATER, CONSTRAINT_LESSER, CONSTRAINT_NOT_EQUAL. The relational constraints are on expressions that are built using inheriters of class EXPR, say: - constants from EXPR_VALUE; - addition, substraction, multiplication from EXPR_ADD, EXPR_SUB and EXPR_MUL; - absolute value from EXPR_ABS; - the conversion from an item to an integer (possible only for items of numeric or ordered groups) with EXPR_ITEM. The constraints on couple take 2 items and the item expression take one item. In any of these cases, items can be or true items (ITEM_ITEM) or variable items (ITEM_VAR). A variable is attached to a group and can take any value into it. The description is built by putting constraints into the the constraint set. The constraints set records the constraint in several groups of bound constraints. Two constraints are bound together if they share the same variable. The class ITEM_COLLECTOR serves the purpose of enumerating the items of a constraint. Such a binding relation define equivalent classes that are used to group the constraints together into CONSTRAINT_GROUP. At the end of the description the constraint set contains - an unbound constraint group that does not depend on any variables; - a list of constraint groups that have variables such that any pair of group in the list have a separate set of variables. Exercice: add some new logical operators like and, or, ... Transformation of the description --------------------------------- In that step, the constraints are transformed to a AND/OR tree of the possible permutations. The possible permutations are recorded using a BIT_STRING. Here is how. Let get two groups: A and X. The group A is made of the item a, b, c. The group X is made of the item x, y, z. The possible permutations from A and X are listed below: {{{{ +-----+-----------+---------+ | A | a | b | c | number | +-----+---+---+---+---------+ | | x | y | z | 0 | | | x | z | y | 1 | | X | y | x | z | 2 | | | y | z | x | 3 | | | z | x | y | 4 | | | z | y | x | 5 | +-----+---+---+---+---------+ }}}} Each of these permutation have received a number that identifies it. That number is used for the BIT_STRING indexes. For example, the possible permutations where b is associated with z are the ones of number 1 and 3 then the corresponding bit string value is: {{{{ index: 0 1 2 3 4 5 value: 0 1 0 1 0 0 }}}} For example, the possible permutations where c is not associated with y are the ones of number 0, 2, 3, 5 and 3 then the corresponding bit string value is: {{{{ index: 0 1 2 3 4 5 value: 1 0 1 1 0 1 }}}} So if the problem is to find how to arrange A with X in a such way that b is with z and c is not with y, a sample or between the possible combinations gives the solution: {{{{ index: 0 1 2 3 4 5 (P1) b with x: 0 1 0 1 0 0 (P2) c not with y: 1 0 1 1 0 1 ------------- (P1) and (P2): 0 0 0 1 0 0 }}}} The solution is permutation 3: a with y, b with z, c with x. For N groups, the program manages (N * (N-1))/2 pair of possible permutations. The AND/OR tree is created by CONSTRAINT_SET that simply make a and of the sub trees created by each of the group of constraint CONSTRAINT_GROUP it contains. The CONSTRAINT_GROUP enumerate all possible combination of the variables and when a combination is consistent for the set of logical constraints, it generates a AND list of the possible permutations that the combination represent. The result is a OR of all the detected possibilities. The masks are built by using an instance of MASK_BUILDER. Exercice: explain how permutations are numbered. Exercice: try to improve the time used for the transformation by challenging the variables before each invocation of 'get_node' in 'get_node_of_var', class CONSTRAINT_GROUP. Trick: add a deferred feature 'can_challenge' in CONSTRAINT_LOGICAL. Exploration of the solutions ---------------------------- During this step, the possible combinations of the AND/OR tre are enumerated using the BACKTRACKING behaviors. When a solution is possible, it is checked to see if it is consistent. In effect, it is not possible to detect all impossibilities during the exploration. The class SITUATION is used to do all that stuff. Exercice: try to improve the checking of the consistency of the presumed solutions. You wil find it in class SITUATION, the feature is 'try_solution'. .def [[:upper:]_]\{2,\} & .def {{{{
.def }}}} 
.def ^Exercice: & .sty .exercice { color: green; font: small-caps bold; }