operator: explain

    description:
        explain[op] seq
        given a cause structure, and an input sequence, find the possible cause
        See here for why we would want to do this:
        Parsimonious Covering Theory with Causal Chaining and Ordering Constraints:
        https://github.com/garrettkatz/copct

    examples:
        -- given this knowledge:
        cause |c> => |a> . |b>
        cause |d> => |a> . |b>
        cause |e> => |d> . |f>

        -- given this sequence: |a> . |b> . |f> . |a> . |b>
        -- find possible causes:
        -- note that even though it prints them all out, it only returns the shortest sequence:
        explain[cause] ssplit |abfab>
            e . c
            e . d
            e . a . b
            c . f . c
            c . f . d
            d . f . c
            d . f . d
            c . f . a . b
            a . b . f . c
            a . b . f . d
            d . f . a . b
            a . b . f . a . b
            |e> . |c>
            
        -- let's verify a couple of these:
        -- NB: we don't use the ssplit operator to make it clear the input is really a sequence, not a string:
        sexp[cause] (|e> . |c>)
            |a> . |b> . |f> . |a> . |b>

        sexp[cause] (|c> . |f> . |d>)
            |a> . |b> . |f> . |a> . |b>


        -- given this knowledge:
        cause |p> => |g> . |m> . |r>
        cause |t> => |p> . |p>
        cause |x> => |p> . |g>
        cause |z> => |r> . |p>

        -- find possible causes for: |g> . |m> . |r> . |g> . |m> . |r>
        explain[cause] ssplit[" . "] |g . m . r . g . m . r>
            t
            p . p
            g . m . z
            x . m . r
            g . m . r . p
            p . g . m . r
            g . m . r . g . m . r
        
        
        -- learn some knowledge about food:
        -- see breakfast-menu.sw
        seq |food: waffles> => |word: waffles>
        seq |country: Belgium> => |word: belgian>
        seq |food: strawberries> => |word: strawberries>
        seq |food: berries> => |word: berries>
        seq |country: France> => |word: french>
        seq |food: toast> => |word: toast>
        seq |meal: breakfast> => |word: breakfast>
        seq |food: egg> => |word: egg>
        seq |food: eggs> => |word: eggs>
        seq |food: bacon> => |word: bacon>
        seq |food: sausage> => |word: sausage>
        seq |food: sausages> => |word: sausages>
        seq |number: 2> => |word: two>
        seq |food: cream> => |word: cream>
        seq |food: belgian waffles> => |word: belgian> . |word: waffles>
        seq |food: maple syrup> => |word: maple> . |word: syrup>
        seq |food: whipped cream> => |word: whipped> . |word: cream>
        seq |food: hash browns> => |word: hash> . |word: browns>
        
        -- define our read operator:
        apply-word |*> #=> |word:> __ |_self>
        read |*> #=> apply-word ssplit[" "] replace[",", ""] remove-suffix[1] remove-prefix[1] remove-prefix["text: "] to-lower |_self>

        -- test it out:
        read |text: "Two eggs, bacon or sausage">
            |word: two> . |word: eggs> . |word: bacon> . |word: or> . |word: sausage>

        -- now use our explain[seq] operator:
        explain[seq] read |text: "Two eggs, bacon or sausage">
            |number: 2> . |food: eggs> . |food: bacon> . |word: or> . |food: sausage>
        
        -- now a couple of bigger examples:
        explain[seq] read |text: "Two eggs, bacon or sausage, toast, and our ever-popular hash browns">
            |number: 2> . |food: eggs> . |food: bacon> . |word: or> . |food: sausage> . |food: toast> . |word: and> . |word: our> . |word: ever-popular> . |food: hash browns>

        explain[seq] read |text: "Light Belgian waffles covered with strawberries and whipped cream">
            |word: light> . |food: belgian waffles> . |word: covered> . |word: with> . |food: strawberries> . |word: and> . |food: whipped cream>
        
        
        -- learn a different set of knowledge:
        -- see cause3.sw
        pattern |node: 1: 1> => |fred>
        pattern |node: 1: 2> => |freddie>
        pattern |node: 1: 3> => |smith>
        pattern |node: 1: 4> => |smithie>
        pattern |node: 1: 5> => |fred> . |smith>
        then |node: 1: *> => |person: Fred Smith>
        
        pattern |node: 2: 1> => |mazza>
        then |node: 2: *> => |person: Mary>
        
        pattern |node: 3: 1> => |hey>
        then |node: 3: *> => |greeting: Hey!>
        
        pattern |node: 4: 1> => |what's>
        pattern |node: 4: 2> => |what> . |is>
        then |node: 4: *> => |question: what is>
        
        pattern |node: 5: 1> => |up>
        then |node: 5: *> => |direction: up>
        
        pattern |node: 6: 1> => |having> . |a> . |baby>
        then |node: 6: *> => |phrase: having a baby>
        
        pattern |node: 7: 1> => |in> . |the> . |family> . |way>
        then |node: 7: *> => |phrase: in the family way>
        
        pattern |node: 8: 1> => |up> . |the> . |duff>
        then |node: 8: *> => |phrase: up the duff>
        
        pattern |node: 9: 1> => |with> . |child>
        then |node: 9: *> => |phrase: with child>
        
        pattern |node: 10: 1> => |phrase: having a baby>
        pattern |node: 10: 2> => |phrase: in the family way>
        pattern |node: 10: 3> => |phrase: up the duff>
        pattern |node: 10: 4> => |phrase: with child>
        then |node: 10: *> => |concept: pregnancy>
        
        -- our 'read' operator:
        read |*> #=> ssplit[" "] replace[",?", ""] to-lower |_self>
        
        -- if 'then' is not defined for a ket, then return itself: 
        then |*> #=> |_self>

        -- now a quick test of our read operator:
        -- yeah, we don't use apply-word this time.
        read |Hey Freddie what's up?>
            |hey> . |freddie> . |what's> . |up>

        -- now 'explain':
        explain[pattern] read |Hey Freddie what's up?>
            |node: 3: 1> . |node: 1: 2> . |node: 4: 1> . |node: 5: 1>
        
        -- now apply the 'then' operator, that maps nodes to concepts:
        then explain[pattern] read |Hey Freddie what's up?>
            |greeting: Hey!> . |person: Fred Smith> . |question: what is> . |direction: up>
        
        -- another example:
        then explain[pattern] read |Hey Mazza, you with child, up the duff, in the family way, having a baby?>
            |greeting: Hey!> . |person: Mary> . |you> . |phrase: with child> . |phrase: up the duff> . |phrase: in the family way> . |phrase: having a baby>
            
        -- then another layer of 'then explain[pattern]':
        then explain[pattern] then explain[pattern] read |Hey Mazza, you with child, up the duff, in the family way, having a baby?>
            |greeting: Hey!> . |person: Mary> . |you> . |concept: pregnancy> . |concept: pregnancy> . |concept: pregnancy> . |concept: pregnancy>
            
        -- further, we could wrap 'then explain[pattern]' into a new operator:
        explain (*) #=> then explain[pattern] |_self>
        explain read |Hey Freddie what is up?>
        explain read |Hey Mazza, you with child, up the duff, in the family way, having a baby?>
        explain^2 read |Hey Mazza, you with child, up the duff, in the family way, having a baby?>

    see also:
        sexp, cause1.sw, cause2.sw, cause3.sw, breakfast-menu.sw, active-buffer
        
    future:
        an example with depth > 2.

Home