Updated doc

parent 905b0f50
......@@ -126,37 +126,35 @@ library defined in C, this api are,
@findex *current-stack*
@findex gp-make-stack
@findex gp-clear
TODO: make *current-stack* a fluid!
The work is done with state objects containing appropriate stacks, rewind information and the assoq list of bindings. You will have the notion current state that is a fluid representing the current stack for the logic computation. You can create new stacks. The setup is thread safe in the meaning that if you try to set a logic variable that is not associated to the supplied stack then a binding will be done by logically consing it to a datastructure that has the same functional behavior as an assoq list on the supplied state data and returned. This means that a large class (but certainly not all) of interop issues between multiple threads is solved. A state or stack datastructure will hold information on what thread-id it belongs and also have a unique id. The stack is actualy 3 stacks, one control stack (nc) one datastack (ns) and a stack of allocated cons cells (ncs). The control stack will contain unwind information, dynwinds and binding information.
The work is done with state objects containing appropriate stacks, rewind information and the assoq list of bindings. You will have the notion of a current 'gp' state that is a fluid representing the current stack in use. Also there is a *current-state* fluid that holds the current assoq binding list/tree. You can create new stacks. The setup can be thread safe in the meaning that if you try to set a logic variable that is not associated to the supplied stack then a binding will be done by logically consing it to a datastructure that has the same functional behavior as an assoq list on the supplied state data and returned. This means that a large class (but certainly not all) of interop issues between multiple threads is solved. A state or stack datastructure will hold information on what thread-id it belongs and also have a unique id. The stack consists of actualy 4 stacks, one control stack (nc) one datastack (ns) and a stack of allocated cons cells (ncs) and one that holds the equivalent of fluids and guards. The control stack will contain unwind information, dynwinds and binding information. The cons stack is not used currently, it can be used to implement closure objects that is created from the stack in stead of the heap, we currently do not use this becuase other overhead is more significant currently e.g. the guile call overhead to C-funcitons. The dynstack is specaial in that its data is recreated at each wind. It represent the expensive winding that essentially originates from the guards and from the equivalent of fluids. Note that multiple reinstation of the other stacks are really cheap in that it does no consing, by allowing e.g. gp-fluid-set! we must pay with copying the stack at each wind, now by separating the small dynstack from the rest we get an important optimization.
@code{*current-stack*}, Holds the current thread local state in a fluid.
@code{*gp*}, fluid that holds the current gp-stack
@code{*current-stack*}, fluid that holds the current assoq
@code{(gp-make-stack id thread-id nc ns ncs)}
Allocate a new state datastructure with identity number @code{id}, thread identity number @code{thread-id} and the sizes of the different stacks. Also it will be stupped so it can be used to unwind to e.g. w can reset the stack to the initialö state calling @code{gp-unwind} with it.
Allocate a new state datastructure with identity number @code{id}, thread identity number @code{thread-id} and the sizes of the different stacks. Also it will be stupped so it can be used to unwind to e.g. w can reset the stack to the initial state calling @code{gp-unwind} with it.
@code{(gp-clear state)}, Reset the state to it's initial setup.
@section Redo safe variables and redo safe parameters.
@findex gp-undo-safe-parameter-guard
@findex gp-undo-safe-variable-guard
@findex *redo-safe-variable-fluid*
@findex *redo-safe-fluid-fluid*
@findex gp-undo-safe-variable-lguard
@findex gp-undo-safe-variable-rguard
A redo safe variable is a ordinary scheme variable that has the property that its state will be saved when the control passes a guard on the stack. It will then be possible to retrieve the old value when the dynamic conditions is right e.g. the fluid value in @code{*redo-safe-variable-fluid*} indicate this according to a rule specified below. This mean that we can in an algorithm have a variable that behaves as a variable and also be able to transparently store the state in e.g. an interaction with the user. but not only this, storage of a state can be included in a postpone algorithm and therefore we can hierachially turn off and on the restorage property. The semantic for undo redo safe parameter follows the same pattern
A redo safe variable is a ordinary scheme variable object or fluid object that has the property that its state will be intelligently stored and retrieved under various premisses. Essentially if there is no mutattion further down the stack we can use the @code{guard} version. Else between lguard and rguard the variable is guaranteed to have restorage property independent of mutation or not.
@code{(gp-undo-safe-variable-guard var kind s}
@code{var} is a guile variable e.g. a boxed value that shall be (possibly) undo safe. We have a control parameter @code{kind} which must not be a GP variable. and s containes the guile-log state.
@code{(gp-undo-safe-variable-lguard var kind s}
@code{(gp-undo-safe-variable-rguard var kind s}
@code{(gp-undo-safe-parameter-guard var val kind s}
@code{var} is a GP variable, val is the value that it will dynamically be bound to for the rest of the evulation of the stack below this guard, and at the return the old value will be restored. We have a control parameter @code{kind} which must can be any value. and s contains the guile-log state.
@code{var} is a guile variable or fluid. We have a control parameter @code{kind} which must not be a GP variable. and s containes the guile-log assoq state.
@code{*redo-safe-variable-fluid*,*redo-safe-fluid-fluid*}, This fluids will be bound to a value that describes if to restore a saved state at reinstation of a state. The rules for restoring the state is in order,
At rewind in context @code{K}, the rules for restoring the state is as follows
@itemize @bullet
@item @code{kind = #t}, restore the state.
@item @code{kind = #f}, do not restore.
@item @code{*redo-safe-variable-fluid* = #t}, restore the state.
@item @code{*redo-safe-variable-fluid* = #f}, do not restore.
@item @code{kind = x, number and *redo-safe-variable-fluid* = y, number} Then we will restore the state if @code{y < x}.
@item if @code{*redo-safe-variable-fluid*} is bound to a procedure, it is assumed to be a predicate and the application of this predicate to @code{kind} decides about restoring the state.
@item @code{K = #t}, restore the state.
@item @code{K = #f}, do not restore.
@item @code{kind, number and K, number} Then we will restore the state if @code{K <= kind}.
@item else do not restore the state.
@end itemize
......@@ -168,7 +166,7 @@ A redo safe variable is a ordinary scheme variable that has the property that it
@findex gp-restore-state
@findex gp-restore-wind
Stack has a stack pointers to undo stacks a data stack and a cons stack, by walking up and down these stacks we can recreate a state. The most lightweight way of winding is to use @code{gp-newframe} and @code{gp-unwind} where you can only go to a previous stack point stored by @code{gp-newframe} and doing that the system forgets everything. This is fast and with no memory overhead. The other mode of operation using @code{gp-store-state},@code{gp-restore-state} and @code{gp-restore-wind} will go the full way and keep everything in memory until you drop and references to the reurned state information and the gc can kick in at recollect the data. @code{gp-store-state} will make a state data structure suitable to be for this mode of operation and @code{gp-restore-state} will restore the infromation either backward or forward in time. Then the setup will be precicles as when the store operation was issued. To note here is that sometimes you would like to use the store and restore operation in a mode that follows a calculation like with the interleaving constructs for this operation it is very nifty to ahve global variables like if they lived on the heap to implement the logic. The downside is that with heap objects you typically cannot restore a state if you would like to do that. Guile log has a nifty framework to define variables that behaves just like these heap variables but with the difference that they are automagicaly restored when the user issues the @code{gp-restore-state}. In order for this to work we use @code{gp-restore-wind} internally when we store and restore information as we follow an algorithmic calculation path.
Stack has a stack pointers to undo stacks a data stack and a cons stack and dynstack, by walking up and down these stacks we can recreate a state. The most lightweight way of winding is to use @code{gp-newframe} and @code{gp-unwind} where you can only go to a previous stack point stored by @code{gp-newframe} and doing that the system forgets everything. This is fast and with no memory overhead. The other mode of operation using @code{gp-store-state},@code{gp-restore-state} and @code{gp-restore-wind} will go the full way and keep everything in memory until you drop and references to the returned state information and the gc can kick in at recollect the data. @code{gp-store-state} will make a state data structure suitable to be for this mode of operation and @code{gp-restore-state} will restore the infromation either backward or forward in time. Then the setup will be precisely as when the store operation was issued. To note here is that sometimes you would like to use the store and restore operation in a mode that follows a calculation like with the interleaving constructs for this operation it is very nifty to have global variables like if they lived on the heap to implement the logic. The downside is that with heap objects you typically cannot restore a state if you would like to do that. Guile log has a nifty framework to define variables that behaves just like these heap variables but with the difference that they are automagicaly restored when the user issues the @code{gp-restore-state}. In order for this to work we use @code{gp-restore-wind} internally when we store and restore information as we follow an algorithmic calculation path.
@code{(gp-newframe s)}, returns the current frame incorporated in a state variable state of the stack in order to be able to backtrack.
......@@ -176,11 +174,18 @@ Stack has a stack pointers to undo stacks a data stack and a cons stack, by walk
The next two command is mirroring the two commands above. But for these we don't impose the restriction to only go back in time, we can freely restore a state. Memory wise and performance this is heavier. But to note is that we do tree compression e.g. we try to reuse as much data as possible.
@code{(gp-store-state) -> state}, Gives a state that can be used to restore a state, this makes the unify stack act well together with call/cc constructions or using continuation closures e.g. it is possible to do continuations with these prolog stacks. Note that this is a very effective storage mechanism, basically the continuation is stored in a tree like structure. Also state does not currently save the storage bank info so it's not perfect.
@code{(gp-store-state s) -> state}, Gives a state that can be used to restore a state, this makes the unify stack act well together with call/cc constructions or using continuation closures e.g. it is possible to do continuations with these prolog stacks. Note that this is a very effective storage mechanism, basically the continuation is stored in a tree like structure.
@code{(gp-restore-state state)}, Restore a state that is saved by gp-store-state
@code{(gp-restore-wind state wind)}, the same as above, but they will not change the dynamic globals e.g. guarded variables to the old state if they where guarded with a @code{k} > @code{wind}.
@code{(gp-restore-wind state wind)}, the same as above, but they will not change the dynamic globals e.g. guarded variables to the old state depending an the algorithm described in teh beginning of this section.
@section The gp fluid
@findex gp-fluid-set
For a guile variable or more prefereble (it is thread safe) for a fluid we can model it as a guile fluid but living on the guile-log stacks in stead. For this to work just use @code{variable-ref, variable-set!, fluid-ref, fluid-set!} and
@code{(gp-fluid-set var val)}
This will bind var to val for the rest of the guile log stacks, e.g. similar to guile's with-fluids.
@section The guile log variables
@findex gp-var!
......@@ -289,12 +294,12 @@ unify (note that although this is false variables could have been unified so @co
@findex push-setup
@findex que-setup
Fluids functions does not change the stack parameters it is a buggy interface because the kind of stack usign should be in the state parameter that should be used as well as input.
Fluids functions does not change the stack parameters it is a buggy interface because the kind of stack sign should be in the state parameter that should be used as well as input.
@code{(gp-make-var),(gp-make-var init)} makes guile log variable on the heap and an optional init value, @code{init}.
@code{(gp-var-set! v x)} set! a guile-log variable without backtracking !danger! do not use this anywhere else then a before a @code{gp-var-set} have been
issued on the variable.
@code{(gp-var-set! v x)} set! a guile-log variable without backtracking !danger! do not use this anywhere else then a before a first @code{gp-var-set} have
been issued on the variable.
@code{(gp-var-set v x)} set a guile-log variable with backtracking the guile
stack is forced to be used to handle the backtracking.
......@@ -310,43 +315,6 @@ These two should only be used by experts.
N.B. the setup stack is executed before the setup que.
@section guarded state variables
@findex gp-undo-safe-variable-guard
@findex gp-undo-safe-variable-rguard
@findex gp-undo-safe-variable-lguard
@findex gp_with_fluid
These ideoms takes a variable or a fluid as an argument and guard it with
respect to redo/undo semantics in various ways. To understand how it works
we will describe what it can guard. guard will make sure that undo and redo
of state below the current stack point is correctly performed if there is no
mutation of the guarded item below the current stack point. the lguard version
will guard it whatever mutation is happening to the variabe below the stack
point up till an rguard which will guard the item below that stack point if no
mutation is possible.
With the restoration of a state and where we need to patch the current values
of the guarded items we need to decide if we should resore the state or not.
These ideoms as a @code{kind}, denoted @code{k} argument will be compared with
a value @code{K} and restore action will be taken according to the rules.
1) if @code{k = #f}, then no action.
2) if @code{k = #t}, then action.
3) if @code{K = #t}, then action.
4) if @code{K = #f}, then no action.
5) if @code{k,K} are numbers and @code{k > K} then action.
@code{(gp-undo-safe-variable-guard item kind s)}
@code{(gp-undo-safe-variable-rguard item kind s)}
@code{(gp-undo-safe-variable-lguard item kind s)}
The @code{item} is either a variable or a fluid and is what is guarded.
@code{kind} will be used to evaluate if at a restorage of a state it will indeed
patch the variable with the old state or not.
@code{(gp_with_fluid var val s)}
This will take a variable or fluid and simulate guiles @code{with-fluids} on
them but along the guile-log stack in stead of guiles internal stack.
@section Kanren logical variables support
@findex use-logical
@findex leave-logical
......@@ -391,7 +359,7 @@ a method of doing an undoable set.
@node guile-log
@chapter Introduction
Guile log is a basic framework of macrology that implements functionality that can be compared to kanren or prolog. The feature set is close to what can be accomplish with plain kanren but more at the speed of prolog. Usually kanren is a more expressive way of implementation and can many times easier be extended with new features, on the other hand, most features in kanren is available in guile-log and performs about 10x faster then native scheme kanren. Other possibilities are using the kanren interface ontop of guile-log and then the speed difference is about a factor of 2.
Guile log is a basic framework of macrology that implements functionality that can be compared to kanren or prolog. The feature set is close to what can be accomplish with plain kanren but more at the speed of prolog. Usually kanren is a more expressive way of implementation and can many times easier be extended with new features, on the other hand, most features in kanren is available in guile-log and performs about 10x faster then scheme kanren. Other possibilities are using the kanren interface ontop of guile-log and then the speed difference is about a factor of 2.
Guile log performs it's actions in a guile-log mode e.g. small scheme like language that behaves in a certain way defining functions for this environment can be done with sugared functions or with a special macro definition.
......@@ -401,7 +369,7 @@ A failure thunk is a thunk that is evaluated at failure and usually the stack
backtracks in this lambda. The continuation lambda takes a failure thunk as
it's argument which represent the current failure and then execute it's body as the continuation of the algorithm. e.g.
guile-log has one aspect that kanren does not have and this is the notion of going up and down a stack at redo and undo. With this we have a notion that is very similar to a dynamic-wind, which can guard constructs. With this it is pretty simple to instrument tracing to not only trace upward but also at the same point track the backtracking. This is not possible in kanren.
guile-log has one aspect that kanren does not have and this is the notion of going up and down a stack at redo and undo. With this we have a notion that is very similar to a dynamic-wind, which can guard constructs. With this it is pretty simple to instrument tracing to not only trace upward but also at the same point track the backtracking. This is not possible in kanren. With this it is possible to keep the number of guarded variables to a minimum something kanren cannot do due to the lack of stack notion. On the other hand it is possible like in the reference implementation of kanren to get away with guarded variables by either using delimited continuations or using special return values. But for some constructs guarded variables is pretty much needed e.g. collect like constructs.
Kanren does one thing pretty well and that is that it can support a notion of tail-call's. We do have options for guile-log to accomplish this as well and hence it is possible to write algorithms in guile-log without risk blowing the stack.
......@@ -457,6 +425,8 @@ Kanrens version of or-i and and-i e.g. the interleaving versions of 'or' and 'an
Threading is not supported in the lower levels, e.g. umatch in guile-log and here Kanren is much better off. In principle this is something that can be improved uppon, but we postpone that to later versions of guile-log.
guile-log is safe with respect to undo/redo, you can stall everywhere and expect to be able to store the stat, and later retrieve it.
Functions @code{(f args ...)} in guile-log is defines as
@verbatim
(define (f s p cc args ...) code ...)
......@@ -945,7 +915,7 @@ Example:
@node postpone
@chapter Postpone, a framework for postponing guile-log evaluations.
This code is available from @code{(logic guile-log postpone)} You may have noticed that guile log is a framework to do tree searches to meet a certain criteria and during the path in the tree create data structures that are able to undo and also redo it's state. Most people when approaching this will sooner or later be bitten by the NP hardness of many interesting problems. The solution might then be to try intelligent guesses in which branch the gold is hiding. What one would like to do is try a set of branches, freeze the different states and at that point create some sort of index that represent the likelihood of the gold lying buried beneath. Then an overall global decision can be taken and only the most promising paths will be further examined. It is for this use case the following system is constructed.
This code is available from @code{(logic guile-log postpone)} You may have noticed that guile log is a framework to do tree searches to meet a certain criteria and during the path in the tree create data structures that are able to undo and also redo it's state. Most people when approaching this will sooner or later be bitten by the NP hardness of many interesting problems. The solution might then be to try intelligent guesses in which branch the gold is hiding. What one would like to do is try a set of branches, freeze the different states and at that point create some sort of index that represent the likelihood of the gold lying buried beneath. Then an overall global decision can be taken and only the most promising paths will be further examined. It is for this use case the following system is constructed. Postpone mix well with the rest of prolog, but especially the @code{<zip>}, forms might behave unexpectedly due to teh postpone mechansim interfering with the synch and produce bad result.
@chapter Api.
@findex postpone
......@@ -955,7 +925,7 @@ This code is available from @code{(logic guile-log postpone)} You may have notic
G.L. (postpone val power)
G.L. (postpone-frame limit fact maxsize)
@end verbatim
To be able to postpone we must have a baseline from which we will base our restarts e.g. @code{postpone-frame}. The @code{postpone} command will basically evaluate @code{val} and see if it's larger then a certain limit that is governed by an initial value @code{limit} and @code{fact} - a factor that adds to the limit each postpone turn. The @code{power} is used to manage a list of possible restarts for and this list is sorted so that we at restarts will try to use @code{maxsize} first elements of the list. The list is never larger then @code{10 * maxsize}.
To be able to postpone we must have a baseline from which we will base our restarts e.g. @code{postpone-frame}. The @code{postpone} command will basically evaluate @code{val} and postpone if it's larger then a certain limit that is governed by an initial value @code{limit} and @code{fact} - a factor that adds to the limit each postpone turn. The @code{power} is the sorting index used to manage a list of possible restarts for and this list is sorted so that we at restarts will try to use @code{maxsize} first elements of the list. The list is never larger then @code{10 * maxsize}.
@node database
@chapter database
......
......@@ -114,6 +114,7 @@
fact maxsize `())))
s p cc))))
(define (post s p cc)
(rs s *conts*
`((0 ,(gp-store-state s) ,cc) ,@(fluid-ref *conts*) s))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment