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.





Tuesday 7 August 2012

pyUnit A unit testing framework

Pythons unittest module provides organized tests for our modules. Here i am testing my numTOword conversion module which convert large numbers to corresponding natural language representations.  a 111 will be converted to one hundred eleven consisting all lower-case letters. We use string of digits to represent numbers since we have to convert really huge numbers.  The module converts numbers in a range 1 to 10^100, deliberately missing zero.

The use of unit test module is as follows
 #test.py
import unittest
import convert
class testnumberTOword(unittest.TestCase):
 
 
 numwordmapping={
   '1':'one',
   '11':'eleven',
   '111':'one hundred eleven',
   '1111':'one thousand one hundred eleven',
   '11111':'eleven thousand one hundred eleven',
   '111111':'one lakh eleven thousand one hundred eleven',
   '1111111':'eleven lakh eleven thousand one hundred eleven',
   '11111111':'one crore eleven lakh eleven thousand one hundred eleven',
   '2':'two',
   '22':'twenty two',
   '222':'two hundred twenty two',
   '2222':'two thousand two hundred twenty two',
   '22222':'twenty two thousand two hundred twenty two',
   '222222':'two lakh twenty two thousand two hundred twenty two',
   '2222222':'twenty two lakh twenty two thousand two hundred twenty two',
   '22222222':'two crore twenty two lakh twenty two thousand two hundred twenty two',
   '3':'three',
   '33':'thirty three',
   '333':'three hundred thirty three',
   '3333':'three thousand three hundred thirty three',
   '33333':'thirty three thousand three hundred thirty three',
   '333333':'three lakh thirty three thousand three hundred thirty three',
   '3333333':'thirty three lakh thirty three thousand three hundred thirty three',
   '33333333':'three crore thirty three lakh thirty three thousand three hundred thirty three',
   '4':'four',
   '44':'fourty four',
   '444':'four hundred fourty four',
   '4444':'four thousand four hundred fourty four',
   '44444':'fourty four thousand four hundred fourty four',
   '444444':'four lakh fourty four thousand four hundred fourty four',
   '4444444':'fourty four lakh fourty four thousand four hundred fourty four',
   '44444444':'four crore fourty four lakh fourty four thousand four hundred fourty four',
   '5':'five',
   '55':'fifty five',
   '555':'five hundred fifty five',
   '5555':'five thousand five hundred fifty five',
   '55555':'fifty five thousand five hundred fifty five',
   '555555':'five lakh fifty five thousand five hundred fifty five',
   '5555555':'fifty five lakh fifty five thousand five hundred fifty five',
   '55555555':'five crore fifty five lakh fifty five thousand five hundred fifty five',
   '6':'six',
   '66':'sixty six',
   '666':'six hundred sixty six',
   '6666':'six thousand six hundred sixty six',
   '66666':'sixty six thousand six hundred sixty six',
   '666666':'six lakh sixty six thousand six hundred sixty six',
   '6666666':'sixty six lakh sixty six thousand six hundred sixty six',
   '66666666':'six crore sixty six lakh sixty six thousand six hundred sixty six',
   '7':'seven',
   '77':'seventy seven',
   '777':'seven hundred seventy seven',
   '7777':'seven thousand seven hundred seventy seven',
   '77777':'seventy seven thousand seven hundred seventy seven',
   '777777':'seven lakh seventy seven thousand seven hundred seventy seven',
   '7777777':'seventy seven lakh seventy seven thousand seven hundred seventy seven',
   '77777777':'seven crore seventy seven lakh seventy seven thousand seven hundred seventy seven',
   '8':'eight',
   '88':'eighty eight',
   '888':'eight hundred eighty eight',
   '8888':'eight thousand eight hundred eighty eight',
   '88888':'eighty eight thousand eight hundred eighty eight',
   '888888':'eight lakh eighty eight thousand eight hundred eighty eight',
   '8888888':'eighty eight lakh eighty eight thousand eight hundred eighty eight',
   '88888888':'eight crore eighty eight lakh eighty eight thousand eight hundred eighty eight'
   }
 def testnumtowordmapping(self):
  p=convert.numbertoword()
  for number in self.numwordmapping.keys():
   print 'tested' , number 
   self.assertEqual(p.spel(number),self.numwordmapping[number])
 
 def runTest(self):
  self.checknumtowordmapping()
   

unittest.main()

On running the script we see


----------------------------------------------------------------------
Ran 1 test in 0.004s

OK


To perform unittest, we have to make a subclass for unittest.TestCase. An instance for this class will carry tests.
The num_word_mapping is the dictionary containing few known mappings between numbers and their word representations. We have to test the convert module giving each number and comparing obtained outputs with expected values.

the function testnumtowordmapping() checks convert.numbertoword.spell(number)
by applying each test cases in num_word_mapping.

The function assertEqual(ExpectedResult,ObtainedResult)  will introduce exception when the Obtained_Result differs from Expected_Result and the checknumtowordmapping()
skips with reporting the unittest module an exception

The result of test with taking expected value for 777777777 on convwesion as 'seven crore seventy WRONG VALUE seven lakh seventy seven thousand seven hundred seventy seven' is as follows

AssertionError: 'seven crore seventy seven lakh seventy seven
thousand seven hundred seventy seven' != 'seven crore seventy WRONG
VALUE seven lakh seventy seven thousand seven hundred seventy seven'



 The completion of testnumtowordmapping() means that there are no bugs found in the scope of this test case







Say BIG numbers in words

Hello friends ,
here is my python app to convert big numbers into words. for example  13333333333333 will be "thirteen trillion three hundred thirty three billion thirty three crore thirty three lakh thirty three thousand three hundred thirty three". Numbers upto googol(10^100) can be converted this way. Conversion is puerly lexical and so complexity depends only on number of digits.

you can find source code Here 









 

Thursday 2 August 2012

GitPython :Python Git API

    Scripting Git tasks is made simpler using GitPython. We can use it to create local Git applications. Here is a simple example script to perform initial Git setup for our project directory /home/user/myproject. We have already created a new repository in GitHub with url https://github.com/user/test.git. Run the script as follows
python initwithGit /home/user/myproject https://github.com/dileepnandanam/test.git

# initWithGit.py
import git
import commands
import sys
import os
projectdir=sys.argv[1]
remote=sys.argv[2]
modules=os.listdir(projectdir)
g=git.cmd.Git(projectdir)
g.init()
for module in modules:
    g.add(module)
message='first commit'
(stats,op)=commands.getstatusoutput("git commit -m '"+message+"'"+projectdir)
g.push(remote)
Class git makes bindings with git binaries  possible
The statement g=git.cmd.Git(projectdir)
enables us to manage the local repository using object g. We can issue git commands as
  • g.init()
  • g.commit()
  • g.branch(branchname)
  • g.checkout(branchname)
  • g.push(remoteRepo)

We can monitor current repository status through git.Repo
eg.

repo= git.Repo(projectdir)
for branch in repo.heads:
    print branch.name
    print branch.commit

This will display all branches and details of commits corresponding to repository