Wednesday, August 10, 2016

Objective : Solvea 15-puzzle program using a realtime search algorithm.  
The 15-puzzle problem is some arrangement of numbers 1 to 15 in a 4 x 4 grid with 16 square blocks labeled 1 to 15 and one blank square. The blocks need to be arranged so that they are in order from any starting configuration. 

We described the A* algorithm yesterday.
Now, we use a real time algorithm as described by Ian Parberry. It is designed using both greedy and divide-and-conquer techniques. 
The algorithm is generalized for (n^2-1) grid puzzles. 

The algorithm is described as follows: 
procedure puzzle(n) 
if n == 3 then solve by brute force else 
          use a greedy algorithm to put the first row and column into place 
          call puzzle(n-1) to solve remaining rows and columns. 

Step 2 above places tiles in the first row ( 1 <=k <=n ) into place at locations (1, k) followed by  
(2 <= k <=n) tiles into place at locations (k,1) for 2 <=k <= n into place, one at a time. 

The implementation looks something like this: 

Void Solve(Board<Location> b, Board<Location> goal, int n, Location blank) 
{ 
For (int k = 1; k <= n/2; k++) 
{ 
Var tile = goal[1,k]; 
Var location = getPosition(b, tile); 
If (location.row > 1 && location.col > N/2) 
{ 

If (k == 1)  
    Move_the_blank_to_right_adjacent(1,2,blank.row, blank.col); 
else  
    Move(2,k-1,blank.row, blank.col); 

If (k> 1) 
Move_the_blank_to _right_adjacent(1,k+1, 2,k-1) 

// move the target tile diagonally to nearest axis 
If (location.row-1 > location.col-1) 
            Move_target_tile_to_goal_col(1,k,ref  location.row, ref location.col) 
Else 
            Move_target_tile_to_goal_row(1,k, ref location.row, ref location.col) 



// location is updated by reference 
//move the target tile horizontally  or vertically 
Move_target_tile_to_goal(1,k, ref location.row, ref location.col) 
         // assert( location.row ==1 || location.col == k); 

}else{ 
 // similar 
} // end else 


} // end for 
} 



To move a tile vertically up, the blank must move from its right anticlockwise to the position right above the tile so that the tile can take its place. 
To move a tile horizontally to the left, the blank must move anticlockwise to the tile’s left so that the tile can take its place. 
To move a tile diagonally to the left, the blank must move anticlockwise to the position right above the tile, so that he tile can take its place and the blank can come down. From this position, the blank has to move clockwise until it is to the adjacent left of the tile so that the tile can take its place.



Location GoAntiClockwiseAround(Location center, int n, int steps)
{
var current = center;
for (int i = 0; i < 8 && steps; i++)
{
switch(i)
{
case 0:
    if (center.row - 1 > 0){
       current.row = center.row - 1;
       current.col = center.col;
       steps--;
    }
    break;
case 1:
    if (center.row  - 1 > 0 && center.col - 1 > 0){
       current.row = center.row - 1;
       current.col = center.col - 1;
       steps--;
    }
    break;
case 2:
    if (center.col -1 > 0){
       current.row = center.row;
       current.col = center.col - 1;
       steps--;
    }
    break;
case 3:
    if (center.row + 1 < n && center.col - 1 > 0){
       current.row = center.row + 1;
       current.col = center.col - 1;
       steps--;
    }
    break;
case 4:
    if (center.row + 1 < n){
       current.row = center.row + 1;
       current.col = center.col;
       steps--;
    }
    break;
case 5:
    if (center.row + 1 < n && center.col + 1 < n){
       current.row = center.row + 1;
       current.col = center.col + 1;
       steps--;
    }
    break;
case 6:
    if (center.col + 1 < n){
       current.row = center.row;
       current.col = center.col + 1;
       steps--;
    }
    break;
case 7:
    if (center.row - 1 > 0 && center.col + 1 < n){
       current.row = center.row - 1;
       current.col = center.col + 1;
       steps--;
    }
    break;
default:
   break;
}
}
return current;
}

Tuesday, August 9, 2016

Objective : Solve a 8-puzzle program using the A* search algorithm. 


The 8-puzzle problem is some arrangement of numbers 1 to 8 in  a 3 x 3 grid with 8 square blocks labeled 1 to 8 and one blank square. 
The blocks will be arranged so that they are in order. 


The A* algorithm is like this: 
Take a snapshot of the puzzle as it appears initially and put it in the priority queue.  
We keep track of previous snapshot and current snapshot.  
The current snapshot is the one in the priority queue and the previous initially is null. 
We remove the snapshot with the minimum priority and insert into it all the neighbouring snapshots.
A neighbouring snapshot is one with that can be reached in one move. 
The priority for a snapshot is found by counting the number of blocks in the wrong position,  
plus the number of moves made so far to get to the snapshot. 
The minimum number of moves must at least be the priority of a snapshot. 
We repeat the procedure until desired goal snapshot is found. 




The priority or cost of a particular state is described in terms of three parameters
f, g and h
g is the cost it took to get to that square and is the number of snapshots we passed from the start
h is our guess to how much it will take to reach the goal and is counted as the number of squares that are not in their place
f = g + h
A star is also called the best path algorithm
The algorithm is described this way:
var open = new List<8Puzzle>();
var closed = new List<8Puzzle>();
void BestPath(8Puzzle start, 8Puzzle goal, ref List<8Puzzle> open, ref List<8Puzzle> closed)
{
open.add(8Puzzle);
while (open.Count > 0)
{
     var q = open.min();
     open.remove(q);
     var neighbors = getNeighbors(q)
     foreach (var neighbor in neighbors){
             if (neighbor == goal) return;
             neighbor.parent = q
             neighbor.g = q.g + distance(q, neighbor)
             neighbor.h = distance(goal, neighbor)
             neighbor.f = neighbor.g + neighbor.h
             
             var seen = open.First( x == neighbor);
             if (seen != null && seen.f < neighbor.f) continue;
             seen = closed.First(x == neighbor);
             if (seen != null && seen.f < neighbor.f) continue;
             open.add(neighbor)
           }
     closed.Add(q);
}
}

Monday, August 8, 2016

Today we continue our discussion of the  paper titled "Pelican: a  building block for exascale cold data storage". Pelican treats a group of disks as a single schedulable unit. Resource restrictions such as power consumption, vibrations and failure domains are expressed as constraints over these units.
With the help of resource constraints and scheduling units, Pelican aims to be better than its over provisioned counterpart racks using computations in software stacks.
We were discussing the evaluation of Pelican and listing out the metrics chosen. To compare the evaluations, a simulator was used in addition to the Pelican hardware rack and the simulator and the rack were cross validated. It was configured in such a way that the prototype Pelican rack hardware matched the simulator. Traditionally, simulating hard disk-based storage accurately is very hard due to the complexity of the mechanical hard drives and their complex control software that runs on the drive. We were discussing the completion time. The completion time increased linearly by the order of 3 for an increase by 64 times the number of requests. The simulator and the rack performed very much like each other. 
Another metric used was the average reject rate.  This measures the requests that are not serviced because the queues are full and the workload is higher than what Pelican can service. It represents the average fraction of requests rejected. In all the experiments, the average incoming rate is 8 requests per second because the NIC card is the bottleneck.
Pelican was also measured for throughput.
Throughput was the same between tge simulator and the rack. This gave more confidence on the results. For throughput, the impact of spinning up disks is small

#puzzle
There are 5 pirates and they have to split 100 gold coins between themselves. The pirates have seniority levels from A to E. The rules of distribution are : 
The most senior pirate proposes a distribution of coins.
All pirates vote on whether to accept the distribution.
If the distribution is accepted, the coins are disbursed and the game ends.
If not, the proposer is thrown and dies, and the next most senior pirate makes a new proposal to begin the system again.

In case of a tie vote the proposer can has the casting vote
Rules every pirates follows.
Every pirate wants to survive

Given survival, each pirate wants to maximize the number of gold coins he receives.
Solution : The answer is 98 coins.
This follows from a tail recursion
If only D and E are there, it will be a distribution of (100, 0) because D has a casting vote
If only C, D and E are there, it will be a distribution of (99,0,1) because C can get enough votes
If B, C, D and E are there, it will be a distribution of (99,0,1,0) because B can get enough votes
if A, B, C, D and E are there, it will be a distribution of (98, 0, 1, 0, 1) to get enough votes.
#codingexercise
Add two numbers without using arithmetic operators
// half adder
int Add (int x, int y)
{
while (y != 0)
{
    int carry = x & y;
    x = x ^ y;
    y = carry  << 1;
}
Return x
}
eg:
add (011, 101)
S, C
110 , 010
100, 100
000, 1000
1000, 000

Similarly,
int Subtract (int x, int y)
{
while (y != 0)
{
    int borrow = (~x)  & y;
    x = x ^ y;
    y = borrow << 1;
}
Return x
}

Sunday, August 7, 2016

Today we continue our discussion of the  paper titled "Pelican: a  building block for exascale cold data storage". Pelican treats a group of disks as a single schedulable unit. Resource restrictions such as power consumption, vibrations and failure domains are expressed as constraints over these units.
With the help of resource constraints and scheduling units, Pelican aims to be better than its over provisioned counterpart racks using computations in software stacks.
We were discussing the evaluation of Pelican and listing out the metrics chosen. To compare the evaluations, a simulator was used in addition to the Pelican hardware rack and the simulator and the rack were cross validated. It was configured in such a way that the prototype Pelican rack hardware matched the simulator. Traditionally, simulating hard disk-based storage accurately is very hard due to the complexity of the mechanical hard drives and their complex control software that runs on the drive. We were discussing the completion time. The completion time increased linearly by the order of 3 for an increase by 64 times the number of requests. The simulator and the rack performed very much like each other. 
The next metric used was time to first byte.  This is the time between a request being issued by a client and the first data byte being sent to the client. This includes the queuing delay and any disk spin up and volume mount delays By its nature, the factors that affect the completion time also affect the time to first byte. Consequently we expect the graph to be linear as well and indeed it turned out to be very similar to the graph for the completion time.
The Service time was another metric used. This is the time from when a request is dequeued by the scheduler to when the last byte associated with the request is transferred. This includes delays due to spinning up disks and the time taken to transfer the data but excludes the queuing delay. As such it focuses on the scheduler status updates to the task. It differs from the completion time in that it excludes the queuing delay and focuses only on the performance of the disks. The charts for service time is therefore different from that for completion time or the time to first byte. The service time dropped from 15 sec to 5 sec as requests increased 64 times for both the simulator and the rack.  This showed that the scheduler does better with increasing loads  and that the time to spin up disks is reduced while remaining within the constraints.
#codingexercise
A person has 3000 bananas and a camel. The person wants to transport maximum number of bananas to a destination which is 1000 KMs away, using only the camel as a mode of transportation. The camel cannot carry more than 1000 bananas at a time and eats a banana every km it travels. What is the maximum number of bananas that can be transferred to the destination using only camel (no other mode of transportation is allowed)
The answer is 533 1/3 bananas.
The camel cannot come back if it makes a straight run to the destination. There will not be any bananas to unload at the destination and there won't be any bananas left to eat so that the camel can return.
The maximum distance the camel can travel is 500 kms for the thousand bananas loaded on it. Therefore there are intermediate stations to stop before reaching the market. Let us say these stations are A,B, C  ... in the order from source to destination.
To unload 3000 bananas in max hypothetical unload of 1000 bananas each three forward trips and two return trips are at least needed. The first segment must at least have five trips, the next segment must be less than this five and for a longer distance in order to save bananas and further decreasing from that point on. So we have 5, 3, 1 number of trips and the cost of each segment can be considered as 5 bananas / km, 3 bananas per km and 1 banana per km to the destination.
The camel can carry at most 2000 bananas from point A and 1000 bananas from point B to destination.
3000 - 5 PA = 2000   => PA = 200 kms
2000 - 3 AB = 1000   => AB = 333 + 1/3 kms
BM = 1000-200-333 1/3 = 466 2/3 kms
The camel arrives at the destination with 533 1/3 bananas.