Newbie questions about Pliant

Newbie questions about Pliant

Metaprogramming, first steps

My final goal is to do program induction (automatic program
generation) in Pliant. But I have never atempted meta
programming in Pliant
Message posted by marcus on 2004/09/14 19:12:36
How can I link the created expression shown below to a module?

module "/pliant/language/compiler.pli"

gvar Address x := (expression constant 2) evaluate
gvar Int i := x map Int
console i eol
Message posted by marcus on 2004/09/14 21:32:01
There was a typo in my previous posted program. Here is what I meant:

module "/pliant/language/compiler.pli"

gvar Address x 
(expression constant 2) evaluate x
gvar Int i := x map Int
console i eol

What I basically want, is to create an expression, evaluate and print its result.
Message posted by hubert.tonneau on 2004/09/14 21:35:59
Your sample seems a bit strange to me, because you try to do meta programming
outside any context, what I have never done.
If you code did happen in a meta function, then the context expression would be
provided as the meta argument.


Now, if you want to make your code run anyway outside any context, here is how
to build a minimal context:

module "/pliant/language/compiler.pli"

gvar Link:Module m :> new Module
m include (the_module "/pliant/language/basic/safe.pli")
gvar Link:Expression e :> new Expression
e module :> m

gvar Address x := (expression constant 2 near e) evaluate
gvar Int i := x map Int
console i eol
Message posted by marcus on 2004/09/14 22:09:20
I am thinking about using Pliant (instead of Lisp) in my Genetic Programming 
course. And I am trying to gage how hard it would be for my students to do  
the first assignment in Pliant.

In the first assignment, they are asked to create a set (of a given max size)
of randomly generated expressions (of a given max size). An expression is defined
inductively as
- a number, in the range 1 to 10, is an expression
- a op b is an expression, where op is +, -, * or /, and a and b are numbers.

Once the set of programs is created, they should print the expressions 
(in infix notation) and their respective values

I have decided to propose such exercise because one of the first stages in GP is 
the random creation of programs (expressions) of a given max size.

From my rusted Lisp experience, I remember that to create and eval an expression
one needs to create the S-expression (i.e., the list where first element is an 
operator the the rest are operands) and then eval it via the eval command.

This what motivated me to write that example.
Message posted by hubert.tonneau on 2004/09/14 22:58:52
With Pliant you have a bit more details that have to be specified, as compared
to Lisp, because:
. Pliant is typed (which is a must on any large project to early detect stupid
  bugs)
. It has namespace notion (which is the reason for the need of a context as
  answered to your previous mail)
. It's a true compiler

The last point means that you can get very efficient result, be you have to
compile at the right place, because compiling is slow.

You can imagine three order of magnitudes:
cost 1: evaluating a precompiled function in a compiler
cost 100: evaluating an expression in an interpreter
cost 10000: compiling a expression to a function (or evaluating an expression
            in a compiler since it's the same)


Here is an example:

Let's evaluate
x + 3
where x is 5

First of all, we could build:
function f x -> y
  arg Int x y
  y := x + 3
which is slow,
then we can apply f to 5, which is fast.

On the other hand, we could build
5 + 3
through substituting in the expression,
then evaluate,
and it will be slow, because Pliant evaluation is compiler in facts, as opposed
to an interpreter.

So, the question for your subject might be: can we have fiew operations
needing to compile a set of functions, then just apply the functions, I mean
do we reuse the same expression quite a lot of time on different set of datas,
or do we use each function only once ?

Message posted by marcus on 2004/09/14 23:28:38
> So, the question for your subject might be: can we have fiew operations
> needing to compile a set of functions, then just apply the functions, I mean
> do we reuse the same expression quite a lot of time on different set of datas,
> or do we use each function only once ?

In GP, programs are automatically created by evolving a predefined set of functions 
applied to a predefined set of data. 

During the run of the GP algorithm, each candidate program is evaluated to
measure how fit it is for the solution of a given goal. The ones that are more 
fit have more chances of being further "genetically evolved".

Hence, you can consider that all automatically created candidate programs need
to be evaluated at each run of the algorithm. And we can have thousands of 
candidate programs.
Message posted by hubert.tonneau on 2004/09/14 23:37:06
Here is a sample program where we build the function from the expression,
then apply it to the data.
We pick three random functions, and apply each of them to three random datas.

module "/pliant/language/compiler.pli"
module "/pliant/util/crypto/intn.pli"

gvar Link:Module m :> new Module
m include (the_module "/pliant/language/basic/safe.pli")
gvar Link:Expression e :> new Expression
e module :> m

function proto x f -> y 
  arg Int x y ; arg Function f
  indirect

function random_expression -> e
  arg Link:Expression e
  # var Int r ; memory_random addressof:r uInt:size ; r := abs:r%20
  var Int r := cast random:20 Int
  if r<10
    e :> expression constant r+1
  eif r=10
    e :> expression immediat x+y substitute x random_expression substitute y random_expression
  eif r=11
    e :> expression immediat x-y substitute x random_expression substitute y random_expression
  eif r=12
    e :> expression immediat x*y substitute x random_expression substitute y random_expression
  eif r=13
    e :> expression immediat x\y substitute x random_expression substitute y random_expression
  else
    e :> expression immediat x

function display e
  arg Expression e
  if e:size>0
    console "("
  if e:ident<>""
    console e:ident
  eif (exists e:value) and (entry_type e:value)=Int
    console (e:value map Int)
  if e:size>0
    for (var Int i) 0 e:size-1
      console " " ; display e:i
    console ")"

for (gvar Int i) 1 3
  gvar Link:Expression ei :> random_expression
  gvar Address a := (expression immediat (function f x -> y { arg Int x y ; y := formula }) substitute formula ei near e) evaluate
  if a<>null and entry_type:a=Function
    gvar Link:Function f :> a map Function
    display ei ; console eol
    for (gvar Int j) 1 3
      gvar Int x := random 10
      console x " -> " (proto x f) eol
Message posted by grings on 2004/10/07 18:11:03
Marcus,

Recently, I have made a similar question to this list.
Based on the answer from Hubert I modified the code to pick-up math expressions 
from console and evaluate.
I don't know if the code is correct, but it works :-)
Note that you can evaluate trigonometric functions as well.


module "/pliant/language/compiler.pli"
module "/pliant/language/parser.pli"
module "/pliant/language/data/string_cast.pli"
module "/pliant/language/ui/ansi_terminal.pli"
module "/pliant/math/functions.pli"

gvar Arrow the_result

meta 'pick the result' e
  if e:size=1
    e:0 compile ?
    the_result := e:0 constant e:0:result:type
    e set_void_result

export 'pick the result'

function evaluate text env -> result
  arg Str text env ; arg Arrow result
  result := null
  var Link:Module e :> pliant_load_module env the_module:"/pliant/language/basic/safe.pli" 0 (null map Module)
  if not exists:e
    return
  var Link:Module m :> new Module
  m name := "sample expression"
  m include e
  m include the_module:"/pliant/math/functions.pli"
  m include this_module
  var List l
  l append addressof:(new Str "'pick the result' ("+text+")")
  var Arrow memo := the_result
  compile_text l m
  result := the_result ; the_result := memo

function testit
  var Str testStr := keyboard_input "Enter something:"
  var Arrow r := evaluate testStr "/pliant/language/basic/safe.pli"

  if r<>null
    console "type of the result is: " entry_type:r:name eol
  if r<>null
    console "result value is " (to_string r entry_type:r "") eol

testit

Message posted by marcus on 2004/10/07 21:12:50
Yep. The code is rather mistifying, but it is interesting what it does.

Just out of curiosity, did you get the idea by looking into the code of the
online pliant interpreter? 
Message posted by grings on 2004/10/08 19:20:16
I made only two slight changes in the original code borrowed from
  http://pliant.cx/pliant/browse/forum/pliant.question/0301VP6/
the inclusion of trigonometric functions, and the keyboard input. 
I just have realized that the post wasn't made by me as well.

In fact I have made squat :o)




Message posted by hubert.tonneau on 2004/10/08 19:26:38
> In fact I have made squat :o)

Squatters are welcome :-)