Add to Google! Add to My Yahoo! Subscribe with Bloglines Pluck Add to NewsGator

March 2008

Google Music

20

March

Found this one by accident this afternoon, thought I’d share.
Running Linux? Is there a song you like?

Google the song in Google Video; who cares what the homebrew video is, just go looking for good audio.
Pull the movie up in Firefox; when the movie finishes buffering, do :

ls -lh /tmp/Flash*

.. and copy the newest file somewhere else, say yer desktop. Now you have a copy of the video.

We just want the audio, so using ffmpeg (sudo apt-get install ffmpeg if you don’t have it), do:

ffmpeg -i [Flash File] [song name] .mp3

And that’s it; one MP3. Use your favourite id3 tool to add tags, and enjoy!


Breadth and depth first search

18

March

Search algorithms
The idea behind search algorithms is to simulate the exploration of a space of states or search space through the generation of successor states already explored.

Tree based search algorithms
Tree search algorithms are the heart of searching techniques. The basic principle is that a node is taken from a data structure, its successors examined and added to the data structure. By manipulating the data structure, the tree is explored in different orders for instance level by level (breadth-first search) or reaching a leaf node first and backtracking (depth-first search).

Definitions

  • State - a representation of a physical configuration.
  • Node - a data structure part of a search tree. A node has the following properties: father, sons, depth and path cost.

States don’t have father, sons, depth and path cost.

Types of problems

  • Deterministic accessible - simple states problem.
  • Deterministic inaccessible - multiple states problem.
  • Non deterministic inaccessible - contingency problem (maybe) - sensors must be used during the execution process. The solution is a tree or a policy. Many times alternates between search and execution.
  • Unknown search space - exploration problem (online).

Selecting a search space
The real world is extremely complex. The search space must be abstracted from the solution process.

Abstracting we have:

  • Abstract state - the set of real states.
  • Abstract operator - combination of real actions.
  • Abstract solution - set of real paths that represents a solution in the real world.

Each abstract action must be easier than the action in the real problem.

 

A simple algorithm

function GeneralSearch(problem, strategy)
  return a solution or failure

Initialise the search tree using the initial state of the problem

loop do
  if there are no candidates for expansion then
    return failure

Choose a leaf node for expansion according to strategy

if the node contains a goal state then
  return the corresponding solution
else
  expand the node and add the resulting nodes to the tree

end

Algorithm implementation

 

function GeneralSearch(problem, QueueingFunction)

nodes <- MakeQueue(MakeNode(InitialState[problem]))

loop do
  if nodes is empty then
    return failure

  node <- RemoveFront(nodes) a leaf node for expansion according
to strategy

  if GoalTest[problem] applied to State(node) succeeds then
    return node

  nodes <- QueueingFunction(nodes, Expand(node,
Operators[problem]))

end

Search strategies
A search strategy is a choice made between the methods used to expand the nodes. Each method has its proper order of expansion.

Strategies are evaluated according to following parameters:

  • Time complexity - the number of generated or expanded nodes.
  • Space complexity - maximum number of nodes presented in the memory.
  • Optimality - the solution found has the minimum cost?

Complexities in time and space are measured in terms of:

  • b - maximum ramification factor of the search tree.
  • d - depth of the solution that has the minimum cost.
  • m - maximum depth of the search space (can be ∞) infinite.

The two strategies presented in this post (breadth and depth first search) are considered uninformed strategies because they only use the information available in the problem definition.

Breadth first search
The breadth first search expands the less deep node.

The data structured used to implement this search algorithm is a queue.

Breadth first search properties
Is complete? Yes, if (b is finite).
Time: 1 + b2 + b3 + … + bd = O(bd). e.g.: exponential in d
Space: O(bd) (maintains all the nodes in memory)
Optimal? Yes, if cost per step is 1; in general is not optimal.

Space is the big problem for can generate nodes at a rate of 1 MB / sec. 24 hours = 86 GB.

Depth first search
The depth first search expands the deepest node.

The data structure used to implement this search algorithm is a stack.

An important note about the depth first search is that it can execute infinite cycles so it’s mandatory to check the states already visited to avoid such infinite cycles.

Depth first search properties
Is complete? No. It is imperfect in spaces of infinite depth or in cyclic paths. Is complete only in a finite search space.
Time: O(bm). Is very bad if m is a lot greater than d. If solutions are dense can be fastest than the breadth first search.
Space: O(bm) e.g.: linear in space
Optimal? No.

Working problem: vacation in Romania
In this post let’s explore a simple states problem as shown in the following picture:

map

Suppose we are going on holiday in Romania. More specifically we are in the city called Arad. We want to go to Bucharest the capital city of Romania and our flight takes off tomorrow.

Breaking down our problem, we have:

  • Objective - go to Bucharest.
  • Search space - several cities to get to Bucharest.
  • Operator - drive through the cities.

In this case a solution is a sequence of cities so that the last city is Bucharest. A valid path could be: Arad, Sibiu, Fagaras, Bucharest.

e.g.: Arad -> Zerind represents a complex set of possible paths, returns, pauses for resting, etc.
To guarantee the realisability, any real state in “Arad” must take us to some real state in “Zerind”.

The problem’s formulation can be:

  • Initial state - Arad
  • Operator (or successor function S(x)) - eg.: Arad -> Zerind, Arad -> Sibiu, etc.
  • Goal test - can be explicit or implicit as x = Bucharest or NoDirty(x).
  • Path cost (additive) - can be the sum of distances, used operators etc.

The solution is a sequence of operators that takes from the initial state to the goal state.

Implementing the breadth and depth first search in C#
The following methods use two classes implemented by Scott Mitchell [1]. The classes are: Node and EdgeToNeighbor.

I just added a new property called PathParent in the node class.

public static void BreadthFirstSearch(Node start, Node end)
{
  Queue<Node> queue = new Queue<Node>();

  queue.Enqueue(start);

  while(queue.Count != 0)
  {
    Node u = queue.Dequeue();

    // Check if node is the end
    if(u == end)
    {
      Console.Write(“Path found.”);

      break;
    }
    else
    {
      u.Data = “Visited”;

      // Expands u’s neighbours in the queue
      foreach(EdgeToNeighbour edge in u.Neighbours)
      {
        if(edge.Neighbour.Data == null)
        {
          edge.Neighbour.Data = “Visited”;

          if(edge.Neighbour != end)
          {
            edge.Neighbour.PathParent = u;

            PrintPath(edge.Neighbour);
          }
          else
          {
            edge.Neighbour.PathParent = u;

            PrintPath(edge.Neighbour);

            return;
          }

          Console.WriteLine();
        }
        /* shows the repeated nodes
        else
        {
          Console.Write(edge.Neighbour.Key);
        } */

        queue.Enqueue(edge.Neighbour);
      }
    }
  }
}

 

public static void DepthFirstSearch(Node start, Node end)
{
  Stack<Node> stack = new Stack<Node>();

  stack.Push(start);

  while(stack.Count != 0)
  {
    Node u = stack.Pop();

    // Check if node is the end
    if(u == end)
    {
      Console.WriteLine(“Path found”);

      break;
    }
    else
    {
      u.Data = “Visited”;

      // Store n’s neighbours in the stack
      foreach(EdgeToNeighbour edge in u.Neighbours)
      {
        if(edge.Neighbour.Data == null)
        {
          edge.Neighbour.Data = “Visited”;

          if(edge.Neighbour != end)
          {
            edge.Neighbour.PathParent = u;

            PrintPath(edge.Neighbour);
          }
          else
          {
            edge.Neighbour.PathParent = u;

            PrintPath(edge.Neighbour);

            return;
          }

          Console.WriteLine();

          stack.Push(edge.Neighbour);
        }
        /* shows the repeated nodes
        else
        {
          Console.Write(edge.Neighbour.Key);
        } */
      }
    }
  }
}

Summary
The formulation of a problem requires abstraction to avoid irrelevant details of the real world so that a search space can be defined and explored.

Later, I’ll dive in more details and explain how to use the breadth and depth search methods. We’ll execute a test case using the Romania map shown in the picture above, print the traveled paths in the screen, calculate the shortest path possible between two cities using Dijkstra’s algorithm and print such a path in the screen.

Before that I recommend the reading of the excellent revision about data structures written by Scott Mitchell [1]. Although I only use the facts exposed in part 5 of Scott’s article: From Trees to Graphs, it’s worth to read starting in part 1.

For now, look and think about the breadth and depth first search implementation in C#.

References
[1] Mitchell, Scott. An Extensive Examination of Data Structures. 2004. Available at <http://msdn2.microsoft.com/en-us/library/aa289152(VS.71).aspx>.

[2] Artificial Intelligence Depot. Blind search. Available at <http://ai-depot.com/Tutorial/PathFinding-Blind.html>.


Get Things Done with Bi-Modal Work Styles

18

March

A big part of staying productive at work involves making conscious decisions about when you’re focusing on a task to the exclusion of everything else and when you’re open to interruptions. Author Tim Ferriss interviewed me recently about my bi-modal work style, which can apply to anyone who’s online and at a computer all day long:

Basically, I’ve got two modes of work: loose/open, and focused/closed. When I’m in “open” mode, my instant messenger status is set to available, I’m surfing, writing, checking email, coding, listening to music with lyrics—getting things done, but in a multitasking way, open to interruptions and tangents.

When I’m in focused/closed mode, I shut down IM, stop checking email, close any windows I’m not using, switch to my ambient music playlist, set a timer, and plow through whatever I’ve got to get done. Typically I go into closed mode when I’m on deadline, or feel like too much time has passed since I checked off something really important on my list.

If you can forgive that shamelessly self-referential act of quoting myself, tell me: what different modes of work are you in during the day? How and when do you move between them? Give it up in the comments.


Happy St Patrick’s Day!

17

March

Paddy was driving down the street in a sweat because he had an important meeting and couldn’t find a parking place.   Looking up to heaven he said, “Lord take pity on me.   If you find me a parking place, I will go to Mass every Sunday for the rest of me life and give up me Irish Whiskey!”

Miraculously, a parking place appeared.

Paddy looked up again and said, “Never mind, I found one.”


Burn an ISO in 3 clicks

16

March

I was working on a project the other day with a friend and he was having some trouble burning an .iso image of one of the Ubuntu 7.04 Herd releases. He asked me about installing gnomebaker or K3B for burning the image. While I have used both of those programs I found that a disk image can be burned very easily directly from the the file location. Here are a few steps to burning a disk image in three clicks.

  1. First, you’ll need to have a .iso image available for burning. This could be located on your desktop, home folder or I’ve even burned an image using this method over on NFS connection. You’ll also need a blank CD or DVD in the drive.
  2. Once you’ve selected your disk image you can right-click the .iso file and select “Write to disk…” (two clicks)
  3. This will open a dialog box letting you verify the disk type, size and burn speed. If all is correct (which it normally is) you can click Burn. Sit back and relax. Your disk will be finished in just a few minutes. (one click)

Done. When finished it’ll ask if you’d like to Eject, Burn Another Copy or if you’re just Done. So very easy.

I find this method much faster and a little more intuitive than the other cd / dvd burning applications. Not to say they aren’t great apps, but if you’re just burning a simple disk image this should be a bit faster. I’ve also had far fewer coasters using this method than I have with the others.


Next Page »

Recent Comments
  • Josef Nankivell: Hi Diptesh, You will need to use Dijkstra's Algorithm to find the shortest path/value when...
  • Diptesh: The above code is good. But i'm tryin to find several alternative paths using stored procedure, with data...
  • kiv: Hi ac adapter! Sounds like a good idea initially, I will look in to this further. Thanks for your comment!
  • kiv: Hi osman, The methods of scrolling on the Viewty change depending one what you are doing. > In the main...
  • ac adapter: What about simply wiping the key (i.e., unmounting the encrypted volume) when the machine is about to get...

Blog Stats

So far I've written 48,853 words in 110 posts. 27 comments have been posted, with a total of 891 words.