guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

schelog like features in guile-unify


From: Stefan Israelsson Tampe
Subject: schelog like features in guile-unify
Date: Sun, 12 Dec 2010 22:43:28 +0100
User-agent: KMail/1.13.5 (Linux/2.6.34.7-0.5-desktop; KDE/4.4.4; x86_64; ; )

Hi, 
I would like to try explainng a little my hackings with guile-unify.
I stoped and worked with a macro framework so that we can get more schemish
doing our analysis. And the approach here is closer to racklog or schelog 
I think. The reason is to test all the core features and have some new ideas.

So, what can this cide look like?

If you would like to play with the code (you crazy guy) use

(use-modules (language prolog macros))

Here we make a function <n> for use by the backtracker it tryies to 
bind unify-var X to 1,2,...,N

(<define> (<n> X N) 
  (<repl-vars> (X)
    (<recur> loop ((I 1))
      (<when> (<= I N))
      (<or> (<=> X I) (loop (+ I 1))))))


(<repl-vars> (v1 , ...) code ...) 

translates schematically to
(let ((v (if (fluid? v) (fluid-ref v) v)) ...)
     code ...)


So one of the new features are that one can work incrementally from a
recursiv repl. And add functionality and explore the repl environment.
So we wan't that data can be reached from global vars. Now specifiying
that these are just unigy variables is a little dirty e.g. the reference 
is there even if we backtracked to the beginning meaning that they may 
cause confusion. I choosed to use a fluid to box them in such to clean this
possible cause of havoc. The downside is a little clumpsy interphase. Actually
a user defined type which essentially is a fluid bud prints better is to 
prefere and I will try to work on this later. Anyway (! a) abstarcts
(fluid-ref a), and (!! a) = (unify-var->scheme-var (! a)) to ease it a little.

(<recur> loop (...) code ...) is very mauch like (let loop (...) code ...)
but I like to mark this out from the schem let version. 
(<or> X Y) will first try X and when that fail try Y
(<=> X Y)  tries to unify X with Y. 

And the code is pretty schemish flow nicly. Cool to note is that one can mix
unify variables and scheme variables as one likes. To note is that making
unify-variables are on the styack and consing are like ordinary consing. If
one chooses to use usual lists there will be a performance hit and also it
does not mix with set! if one likes to use the postpone facilities (set!-ing 
anf e.g. the car of the list will not be traced by the undo mechanism.

So lets introduce two variables a,b
scheme@(guile-user)> (<exec> (a b))
scheme@(guile-user) [1]> (! a)
$3 = <gp>                                                                   
scheme@(guile-user) [1]> (! b)                                              
$4 = <gp>                                                                   
scheme@(guile-user) [1]>    

Add a iteration from one to 10 of a, take out one value

scheme@(guile-user) [1]> (<exec> () (<n> a 10))
scheme@(guile-user) [2]> (! a)                                              
$5 = 1                                                                      
scheme@(guile-user) [2]> (<take> 1 a)
(*r* = (1))
scheme@(guile-user) [2]> *r*                                                
$6 = (1)           
scheme@(guile-user) [2]> (! a)
$7 = 2

Now iterate b from 1 to 5 and take 2 of (a b)

scheme@(guile-user) [2]> (<exec> () (<n> b 5))                 
scheme@(guile-user) [3]> (! b)
$8 = 1                                                                      
scheme@(guile-user) [3]> (<take> 2 `(,(! a) ,(! b)))
(*r* = ((2 1) (2 2)))

ah push ,q to go to the previous repl and let b go from 1 to 10 in stead
scheme@(guile-user) [3]> ,q
$9 = ()                                                                     
scheme@(guile-user) [2]> (! b)
$10 = <gp>
scheme@(guile-user) [2]> (<exec> () (<n> b 10))
scheme@(guile-user) [3]> (<take> 50 `(,(! a) ,(! b)))
(*r* =
     ((2 1)
      (2 2)
      (2 3)
      (2 4)
      (2 5)
      (2 6)
      (2 7)
      (2 8)
      (2 9)
      (2 10)
      (3 1)
      (3 2)
      (3 3)
      (3 4)
      (3 5)
      (3 6)
      (3 7)
      (3 8)
      (3 9)
      (3 10)
      (4 1)
      (4 2)
      (4 3)
      (4 4)
      (4 5)
      (4 6)
      (4 7)
      (4 8)
      (4 9)
      (4 10)
      (5 1)
      (5 2)
      (5 3)
      (5 4)
      (5 5)
      (5 6)
      (5 7)
      (5 8)
      (5 9)
      (5 10)
      (6 1)
      (6 2)
      (6 3)
      (6 4)
      (6 5)
      (6 6)
      (6 7)
      (6 8)
      (6 9)
      (6 10)))

So this works pretty good now, and IS a first step to get an environment
from which one can explore with human guidance. E.g. guided tree search
which is the most cost effective way to make extreemly difficult searches
(yes human experts are an outstanding)

So else, for your knowledge, I'm helping out a little with EuLisp and 
managed to transfer Alex version of Wrights matcher. (The maintainer 
did use a direct translation of Wrights) The cool thing here was to 
bootstrap Alex matcher from the translated Wrigts and get clean maintainable
code and also a significant speed increase.

One thing to note from this discussion is the 'ol $ matcher. I think that it
contains a serious drawback from using hard coded positions in the struct 
layout and I forsee ton's of buggs coming from a change of the struct
definition and failurs from updating all the matchers all over the place.
Smart users use grep in these cases, but I would argue for introducing an 
inderaection. E.g.

(define deer-accesors '(deer-name deer-age ...))   (define at comile time)
($ deer-accesors pat1 , ....)

that translates to the pattern
(and (= deer-name pat1) ...).

Do you agree if this is better then using the array indecies?

Anyway, On my TODO list now is
1. test the repl feature and unbugg it
2. write and test out more of the features
3. a version of <define*> <lambda*> and friends and perhaps some more 
   translation from scheme to 'schelog'
4. add the postpone facilities to repl mode of working
5. Continue with the type-checking (using schelog)
6. Perhaps take an excursion and port some code over to guile
   - kanren works on guile, not well tested.
   - guile-scsh works reasonable for my usage

   - perhaps porting syntax-parse over to guile would be fun
7  try out some other cool scheme packages
8  port the prolog code to use the 'schelog' constructs
9  consider playing with the logic solver in the repo written in prolog
10 factor in a pure scheme version. 
   The idea is to see if a list based stack in stead of a array based
   can bring in more features without suffering from a to significant
   speed detoriation
11 consider the same, but using pure scheme and a array
12 consider list and pure schem versions
13 try to see how fast naitive compilation of prolog/schelog code
14 introduce typechecking inside guile

Oh well, I probably need to fork of a couple of more Stefans, but at least I 
will have fun for another year or two.

Oh, guile-2.0 rocks. I must say that after having using it now for a while. A
big hug to all of you because of that :-)

Cheers
Stefan









reply via email to

[Prev in Thread] Current Thread [Next in Thread]