Monday, 10 September 2012

Python Decorators

Python Decorator is a strategic use of functional programing facilities. Decoration stands for some kind of modifications. Let us consider one example. Consider , we have some function takes one integer and maps to some other integer, take a squaring function for now.
>>> def square(x):
...     return x*x
and we have to make a generalized function which accepts functions of the above kind as arguments and produce new function which do some further maping. take a doubling method for now.
>>> def double(x):
...     return x*2
Now let us make a function mofifier function
>>> def modify(f):
...     def g(x):
...             return double(f(x))
...     return g
now we can have a new function which performs the two mappings squaring and doubling together

command
>>> newFun=modify(square)
>>> newFun(2)
8
we can generalize the use of such function modifying functions with concept of decorators as
>>> @modify
... def square(x):
...     return x*x
 now we have a modified version of function square(x)
>>> square
<function g at 0x93dc64c>
>>> square(2)
8
Just after defining the function square, it is passed to modify() and the result returned is used instead of square().
>>> def decGenerate(mapping):
...     def modify(f):
...             def g(x):
...                     return mapping(f(x))
...             return g
...     return modify
... 
>>> @decGenerate(double)
... def square(x):
...     return x*x
... 
>>> square(2)
8
Here function decGenerator(mappingFunction) returns a function makung functio modify(f) which can be used as decorator



Sunday, 9 September 2012

some magic with python

Here I am trying to discuss about some special method attributes in python.

we define a class like
>>> class myClass:
...     def __init__(self,value):
...             self.value=value
...             print 'object initialized'
And an object instantiation is done by
>>> a=myClass(10)
object initialized
>>> b=myClass(20)
object initialized
This seems usual but the magic is in evaluating the function myClass(value). an expression in the formmyClass(args) causes a call to __init__(self,args) defined inside class myClass.

let us make a new object c with its value attribute as sum of those of objects a and b.
>>> c=myClass(a.value+b.value)
object initialized
>>> c.value
30
It will be awesome if we can perform
>>> c=a+b
object initialized
>>> c.value
30
 We can make this possible by including a magic function __add__ to the class definition of myClass.
>>> class myClass:
...     def __init__(self,value):
...             self.value=value
...             print 'object initialized'
...     def __add__(self,obj):
...             c=myClass(self.value+obj.value)
...             return c
 Here c=a+b is evaluated as c=a.__add__(b)
There are more such methods enables operator overloading for arithmetic operators

Operator Special method
- __sub__(self, other)
// __floordiv__(self, other)
/ __div__(self, other)
% __mod_(self, other)
** __pow__
<< __lshift__(self, other)
& __and__(self, other)
| __or__(self, other)
^ __xor__(self, other)

There are corresponding reflected arithmetic operators too. If we use __radd__ instead of __add__ in above example, c=a+b will be evaluated as c=b.__radd__(a). We can define custom behavior for a lot of operations other than these arithmetic operators, like attribute assignments, comparisons, unary arithmetic operations like '+', '-' etc

Now let us look on some awesome special methods which enables creation of sequence types.

We have a class mySequence
>>> class mysequance:
...     def __init__(self,list):
...             self.value=list
...     def __iter__(self):
...             return iter(self.value)
...     def __getitem__(self,index):
...             return self.value[index]
...     def __len__(self):
...             return len(self.value)
... 
>>> s=mysequance([1,2,3,4,5,6])
 

Now we can perform some  list operations as follows
>>> len(s)
6
>>> s[1]
2
>>> it=iter(s)
>>> for i in it:
...     print i
... 
1
2
3
4
5
6





















Saturday, 1 September 2012

Python iterators, generators and list comprehension

Iterators

Iterators are objects which enables traversal of python sequence data structures like strings, tuples and lists which are so called iterable.
>>> list=[1,2,3,4]
>>> lit=iter(list)
>>> lit
<listiterator object at 0x96abd2c>
 we can use this iterator object to extract elements on the list one by one
>>> lit.next()
1
>>> lit.next()
2
>>> lit.next()
3
>>> lit.next()
4
>>> lit.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
Function next() raise Stopiteration exception when there is no more element in list to traverse.

 we can use iterator object instead of corresponding sequence variables in construct.
>>> tit=iter((1,2,3,4))
>>> tit
<tupleiterator object at 0x96abfcc>
>>> 3 in tit
True 

generators

>>> def listgen(n):
...     for i in range(n):
...             yield i
... 
Python interpret functions like above containing a yield statement in a special way unlike to other functions. When we call the function listgen(n)
>>> g=listgen(5)
>>> g
<generator object listgen at 0xb786af7c>
Instead of executing the function and returning the result, a generator object  corresponding to listgen() is returned. The use of generator object is similar to iterator object.
>>> g=listgen(3)
>>> g.next()
0
>>> g.next()
1
>>> g.next()
2
>>> g.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration 

List comprehension

squares=[i*i for i in range(10)  if i%2==1]
>>> squares
[1, 9, 25, 49, 81]
A list comprehension consists of brackets containing an expression followed by a for clause, then zero or more if clauses. This special construct returns a list. The above list comprehension statement gives same result as
>>> squares=[]
>>> for i in range(10):
...     if i%2==1:
...             squares.append(i*i)
... 
 or
>>>squares=map((lambda x: x*x),filter((lambda x:x%2==1), range(10)))

We can perform nested list comprehension like follows,
>>> matrix=[[1,2,3],[4,5,6],[7,8,9]]
>>> transpose=[[matrix[i][j] for i in range(len(matrix))] for j in range(len(matrix[0]))]
>>> transpose
[[1, 4, 7], [2, 5, 8], [3, 6, 9]] 



 

Friday, 31 August 2012

Functional programming with python

Even we cant depend completely on functional programming, we should employ this approach whenever possible. In that sense, Python is a good platform for mixing up different programming approaches in a most convenient way

Python functional programming facilities

We shall discuss python functional programming capabilities based on following examples

With Python object oriented programming, we can notate an arithmetic progression as
>>> class term:
 def __init__(self,a,d):
  self.value=a
  self.d=d
 def next(self): 
  self.value+=self.d
  return self 

>>> x=term(1,2)
Here x is capable of generating terms in an arithmetic progression with a=0 and common difference d=2, as follows.
>>> x.next() 
>>> x.value
3
>>> x.next() 
>>> x.value
5
>>> x.next()
>>> x.value
7 
We can perform such an abstraction with functional programming facilities as follows.
>>> def term(a,d):
...     return(lambda f: f(a,d))
... 
>>> def next(s):
...     return s(lambda a,d: term(a+d,d))
... 
>>> def value(s):
...     return s(lambda a,b:a)
... 

>>> x=term(1,2)
>>> value(x)
1
>>> x=next(x) 
>>> value(x)
3
>>> value(next(next(next(next(term(1,2))))))
9
Inside term(a,b) a nameless function is defined using lambda expression. The definition of this lambda function contain use of local variables of function term(). The closure property of functional languages facilitate this kind of definition of functions inside a function. Again, this lambda function accepts a function f of the form
f(a,b):
     return expression_on(a,b)

as its argument and apply f on local variables a and b of function term(a,b) then return the result. So this lambda function is a higher order function, that is a function accepts functions as arguments. What is returned by term function is a higher order function which has access on local variables of term(). This ability to use function as return value is called currying.

What's the benefit?

Functional programs contain no side-effects. that is, A function call can have no effect other than to compute its result.


Function term(a,b) returns a higher order function x with a,b as tis local variables. With special functions value(s) and next(s) we can have read access to the local variables. In the second case x is a function object with constant state. In other words state is strictly conserved. in first case, in this style of programming, state change for x occurs  as a side effect for each call to member function next().

Advantage of Eliminating side effects is "Referential transparency"

In first case
>>>x.next().value==x.next().value
False 
in second case
>>>value(next(x))==value(next(x))
True 

Here value(next(x)) returns same value at every time applied on x. That means we can replace this expression with a value whenever it occurs. This property is called referential transparency. No one feel any confusion because it is "Mathematically provable". In first case we can maintain referential transparency by adding some extra object replications instead of just returning a self. But in functional programming approach, it is an inherent characteristic.

Thursday, 30 August 2012

Simple Chess using Recursive Minimax

Here it is just a try to make a chess playing program. The program runs on a very basic recursive minimax algorithm. So it now plays like a novice chess player, and also subjected to usual problems of recursive minimax. The maximum achievable depth for the minimax tree is 10 here. so at most 5 opponent movements can be foretasted. Also a depth of 4 or 5 is practical considering the time taken for each decision. I am trying to implement it by means of non-recursive minimax algorithm and more constraints on cost benefit analysis of each move to upgrade it to a moderate level chess playing program


Here is the source code

Wednesday, 15 August 2012

Applicative Order Evaluation in Scheme

Arguments to functions can be expressions which are to be evaluated inorder to pass values to function. There are two models of evaluation of arguments to functions. Applicative order and normal order evaluation. In normal order evaluation, not all the arguments are to be evaluated. the evaluation of each argument is delayed until it is necessary. Its a lazy evaluation technique. But in the case of applicative order evaluation all arguments are evaluated regardless of the need.
for example consider function "checkrange" which accepts two parameters x and y, then returns true if x coming under the range 0 to y.

(define (checkrange x y)
    (if (< x 0)
        false
        (if (> x y)
            false
            true)))


Here we have two conditions ,where the second is checked only if the first condition fails. Also the value y is used only then.

If we call this function this way 

(checkrange -15 (/ 100 0))

Since x value less then 0 first check satisfies and function should return a #f (boolean false value) and second argument is not evaluated in case of normal order evaluation. But in scheme this would cause error since it perform application order evaluation and so evaluating (/ 100 0) raise division by zero error.
   
We use "if" construct as any other function by passing predicates and expressions as arguments to function. But in Scheme (or lisp) the "if" function is a specially made one since applicative order evaluation makes problems. This scenario will be more clear with the example: Square Roots by Newton's Method.

(define (absolute x)
    (cond ((< x 0) (- x))
        (else x)))
      
(define (good guess x)
    (< (absolute (- (* guess guess) x)) 0.001))


(define (improvguess guess x)
    (/ (+ guess (/ x guess)) 2))
  
(define (sqroot guess x)
    (if (good guess x)
        guess
        (sqroot (improvguess guess x) x)))

Function (sqroot guess x) is recursively called here. The termination of recursion occurs when function (good guess x) returns a boolean true value.
   
In the example let us replace "if" by a user defined function "new-if" which obeys applicative order evaluation, as follows.



(define (new-if x y z)
    (cond (x y)(else z)))

(define (sqroot guess x)
    (if (good guess x)
        guess
        (sqroot (improvguess guess x) x)))

define (p) (p))
       
Function (sqroot (improvguess guess x) x))) will be evaluated whenever the "new-if" function is called, yielding infinite recursive calls.
       
   





Saturday, 11 August 2012

Simulator for a Mythical Machine in JAVA

Mythical machine is an imaginary decimal based computer simulated over real machines. Mythical machine performs very basic computations and has small instruction set and instructions are treated as decimals for simplicity. here is a java version of the simulation.We can type assumbly code and simply run it on the simulated mythical processor which has a register file of 10 registers r0-r9 and having a load store architecture. Contents in memory locations and registers are displayed as output.
You can look at the source code here.