Anda di halaman 1dari 7

Assignment: Amicably Yours

Jaspreet S. Jheeta 2012EE10457,Group 1

1.Algorithm:
The algorithm to generate amicable pairs uses a function needed for evaluation of sum of proper divisors of a natural number. For eg, consider n=10 , sum of proper divisors of 10= 1+2+5= 8 So the function for evaluation of some of proper divisors of a natural no. is dota(a,b,c,d), where a is the natural number itself , b is what I call a counter which increases by 1 after each call, c is the check which is helpful in termination of algorithm when b=c, d is the storage portion where the value of each divisor is being summed up . Note1: In the following explanation two functions of sml, mod and div are used which indicates the remainder and the quotient respectively . a=bq+r, 0<=r<absolute(b) then a div b=q and a mod b = r Example: 10 div 3= 3 and 10 mod 3=1 [10=3*3+1]
dota(a,b,c,d)= dota(a,b+1,c,d+b+(a div b)) = dota(a,b+1,c,d) = d +b + a div b =d+b =d if b<c and a mod b=0 => b is a divisor of a if b<c and not(a mod b)=0 if b=c and b>c*c and a mod b=0 if b=c and b=c*c and a mod b=0 if b=c and not(a mod b)=0

Now this is our basic function what gives us sum of proper divisors of a is when we substitute b=1,c=[(a)^(0.5)],d=(-a)

So we define a more compact function cs(a)=dota(a,b,c,d) with above values substituted in dota Now we will deal with function which will actually deal with the pairs ,i.e. gem(n,i,j) where n is the number till which we have to evaluate amicable pairs , i is as usual the counter and j is the list generated for amicable pairs.
gem(n,i,j) =gem(n,i+1,j) =gem(n,i+1,j) =gem(n,i+1,(i,cs(i))::j) =j if n>=i>=cs(i) if n>=i and i<cs(i) and not(i=cs(cs(i))) if n>=i and i<cs(i) and (i=cs(cs(i))) if n<i

So again we have compressed the function to genAmicable(n)=gem(n,220,[]), where [] indicates empty list .

2.Correctness of Algorithms:
2.1.Correctness of cs(a): (evaluation of sum of proper divisors)

Our function is cs(a)=dota(a,1,[(x)^(1/2)],-a)


Note2: 1.if b is a divisor of a then a can be expressed as a=b*q where q=a div b . Now a/q=b this implies that a mod(a div b)=0 thus a div b is also a divisor. 2. if b<(a)^(0.5) and a mod b=0 then (a div b)=a/b>(a/(a)^(0.5))=(a)^(0.5) thus if check is kept at less than equal to root(a) then a div b wouldn`t be evaluated thus it is incremented in storage when b is detected.

Basis :
for starting case when b=1 and 1 divides every natural number , which implies it is a divisor of a. Thus a mod 1=0 and so the first stored value will be d+1+a div1 = -a+1+a=1 which satisfies the definition of sum of proper divisors which exclude the number itself from the sum.

Induction Hypothesis: (k>1)


Now consider it is correct for b=k and we get divisors {1,a(1),a(2),.....a(m)} d=(1+a(1)+a(2)+....+a(m)+(a/a(m))+(a/a(m-1))+...(a/a(1))) assume k+1<c

Induction step:
For b=k+1 b<c => Case1: if a mod b=0 This implies that b is a divisor of a and a can be expressed as a product of b and q such that q=(a div b).So according to the algorithm the storage component will increase by b+(a div b) and this is in accordance with the definition of sum of proper divisor.

Case2:if not(a mod b=0) This simply implies that b is not the divisor of a so there should be no increment in the storage component d by mathematical definition which is quite clearly indicated by algorithm and thus the return value is d only. If b=c (termination point) Case1:if a mod b=0 Sub-Case1:if a =c*c i.e. a is a perfect square like 1, 4,9,16,....etc. According to mathematical definition if b is a divisor of a and a is a perfect square this implies that only b should be incremented in storage d. Algorithm under these conditions also return d+b Sub-Case2:if a>c*c i.e. a is not a perfect square According to mathematical definition b is a divisor of a and a div b is also a divisor greater than c as c<root(a),thus sum should be incremented by b +a div b Algorithm also returns d+b+(a div b) Case2:a mod b>0 This implies b is not a divisor and simply the function should return d without any increment which is in accordance with the algorithmic response. Note3: Let us check whether a divisor y of a greater than root(a) is left out of sum or not. It is sure by the termination step that the divisibility of y was not checked by our algorithm because it was stopped at b=c<=root(a)<y. Now by saying it is not evaluated doesnt mean that it was not added. We can express a =y*z which implies that a mod z=0 and z<=c<root(a).According to our algorithm z was once checked for divisibility when b=z which we can see was proved correct and hence y was added previously with z as y is in other form a div z. So , we can say that our algorithm for evaluation of sum of proper divisors is correct mathematically . One will argue that what if a<1 then this algorithm will fail but a check will be imposed using an exception while defining code for genAmicables(n) which will only permit values greater than 0 to this function.

2.2.Correctness of genAmicables(n): genAmicables(n)=gem(n,220,[])

Basis:
For n=220, sum of proper divisors of 220 is 284 which greater than i and sum of proper divisors of 284 is 220 therefore the a new character (220,284) would be introduced in empty list j and we can see that (220,284) is an amicable pair. gem(220,220,[])=gem(220,221,[(220,284)])=[(220,284)] as 221>220

Induction Hypothesis: (k>220)


Let the algorithm give all amicable pairs for n=k i.e. we will get list j= [(x(l),y(l)),(x(l-1),y(l1)),......(x(1),y(1))] gem(k,220,[])=gem(k,k+1, [(x(1),y(1)),(x(2),y(2)),......(x(l),y(l))])= [(x(l),y(l)),(x(l-1),y(l1)),......(x(1),y(1))]

Induction step:
Now moving over to b=k+1 gem(k+1,220,[])=gem(k+1,k, [(x(l),y(l)),(x(l-1),y(l-1)),......(x(1),y(1))]) =gem(k+1,k+1, [(x(l),y(l)),(x(l-1),y(l-1)),......(x(1),y(1))]) Now this will check for i=k+1 Case1:i<cs(i) Sub-Case1:i =cs(cs(i)) then another element (k+1,cs(k+1)) would be added in the list gem(k+1,k+1, [(x(l),y(l)),(x(l-1),y(l-1)),......(x(1),y(1))])= gem(k+1,k+2, [(k+1,cs(k+1)),(x(l),y(l)),(x(l1),y(l-1)),......(x(1),y(1))])= [(k+1,cs(k+1)),(x(l),y(l)),(x(l-1),y(l-1)),......(x(1),y(1))]) Subcase2: not(i=cs(cs(i))) then no element would be added in list gem(k+1,k+1, [(x(l),y(l)),(x(l-1),y(l-1)),......(x(1),y(1))])= gem(k+1,k+2, [(x(l),y(l)),(x(l-1),y(l1)),......(x(1),y(1))])= [(x(l),y(l)),(x(l-1),y(l-1)),......(x(1),y(1))]) Case2:i>=cs(i) Then simply return the whole list gem(k+1,k+1, [(x(l),y(l)),(x(l-1),y(l-1)),......(x(1),y(1))])= gem(k+1,k+2, [(x(l),y(l)),(x(l-1),y(l1)),......(x(1),y(1))])= [(x(l),y(l)),(x(l-1),y(l-1)),......(x(1),y(1))]) Note4: Applying the condition i<cs(i) favours us in two ways first by eliminating repitition and occurrence of perfect numbers. Secondly, if you try evaluating for how many numbers this holds

true for n=10^(i) ,you will get that cs(cs(i)) is only evaluated in about 25% numbers thus speeding the evaluation process. This fact was basically tested by writing a modified code which would add 1 if i<cs(i) else 0 till i>n.

So we can say that genAmicables(n) contains all the amicable pairs (x,y) such that x<=n

3.Proof of termination:
1.cs(a)=dota(a,1,[(x)^(0.5)],-a) the function with each call increases the counter ,b`s value by 1 decreasing the value of c-b by 1. The recursion terminates at c=b i.e the set of values of c-b has a lower bound 0,thus , function cs(a) is bound to terminate. 2. genAmicables(n)=gem(n,220,[]) the function with each call increases the counter ,i`s value by 1 decreasing the value of n-i by 1 . The recursion terminates at n-i=-1 i.e the set of values of n-i has a lower bound of -1 , thus, function genAmicables(n) is bound to terminate.

4.Time Complexity:
Time complexity would be evaluated taking some assumptions Assumption 1: addition , subtraction ,logical comparisons and other naive operations take no time. Assumption 2:div , mod and multiplication are bound to take equal time(here we take it unit time) Time complexity for cs(a): Now from i =1 to [ ] apply one div and one mod operation taking the worst possible case So we can conclude that T(cs(a))=2* =O( ) Time complexity for genAmicables(n): There are two parts in this problem one that it will always evaluate cs(i) for all numbers from 220 to n and for only 25% numbers it will further evaluate cs(cs(i)).[refer to Note 4] Taking the worst case i.e. taking form 1 to i-1 all proper divisors of cs(i), cs(i)<=1+2+....+n1+n=(n(n+1))/2

T(genAmicables(n))= 1 + 2 + + 1 + +0.25( (1) + 2 + + ( 1) + ()) T(genAmicables(n-1))= 1 + 2 + + 1+0.25( 1 + 2 + + 1 ) T(genAmicables(n))=T(genAmicables(n-1))+ + 0.25 () <=T(genAmicables(n-1))+ + 0.25 ( ( + 1))/2 <=T(genAmicables(n-1))+ + /4 2 We can use Cauchy Schwartz formula to evaluate
1 1

<=(

(n))^(0.5)<= 1.5 / 2

so T(genAmicables(n))= (. / )+(n*(n+1))/8 =O( )

5.Space complexity:
1.function cs(a)=dota(a,1, , )

So due to application of tail recursion by introduction of d what I refered to the storage for sum of proper divisors the space complexity of the function is just proportional to 0 i.e. 1. S(dota(a,b,c,d))=S(dota(a,b+1,c,d`))+0 Thus S(cs(a))=O( ) 2.function genAmicables(n)=gem(n,220,[]) Due to application of tail recursion we just get introduction of new elements to the old list to form a new list stored in the function only thus the space complexity is proportional to 1 as the list has always space complexity proportional to 1. S(gem(n,i,j))=S(gem(n,i+1,j`))+0 Thus S(genAmicables(a))=O( )

6.Applying Tail Recursion:


Both the functions cs(a) and genAmicables(n) are both tail recursive and no further improvement in the algorithms could be done to make any other command tail recursive

The tail recursion has been introduced by what I refer to as the storage variable (d and j) which immediately stores the value by applying the operation rather tahn letting it expand after recursive calling and then evaluation of the value of the function. So no further improvement related to reducing space complexity can be introduced.

7.To limit the value of sum o f divisors to upper bound valOf(Int.maxInt):


Just change the sum of proper divisors algorithm a little bit to ignore those numbers for which the sum of divisors is greater than N where N=valof(Int.maxInt) Now the necessary changes in the dota(a,b,c,d) algorithm(i.e. the algorithm for sum of proper divisors) will be just checking the condition if new increment will make it overflow or not .For that just put one condition in both b<c and b=c branches of a mod b=0 that if (b+(a div b))>valOf(Int.maxInt)-d then just return 0. dota (a,b,c,d) = 0 else normal algorithm Also raise an exception to remove the possibility of getting n<1 in definition of genAmicables(n) genAmicables(n) = exception invalidnumber = gem(n,1,[]) if n<1 if n>=1 if a mod b=0 and b+a div b>valOf(Int.maxInt)-d

Anda mungkin juga menyukai