software

Quantum Reasoners Hold Key to Future Web

Last year, a company called DWave Systems announced their quantum computer (the ‘Orion’) – another milestone on the road to practical quantum computing. Their controversial claims seem worthy in their own right but they are particularly important to the semantic web (SW) community. The significance to the SW community was that their quantum computer solved problems akin to Grover’s Algorithm speeding up queries of disorderly databases.

Semantic web databases are not (completely) disorderly and there are many ways to optimize the search for matching triples to a graph pattern. What strikes me is that the larger the triple store, the more compelling the case for using some kind of quantum search algorithm to find matches. DWave are currently trialing 128qbit processors, and they claim their systems can scale, so I (as a layman) can see no reason why such computers couldn’t be used to help improve the performance of queries in massive triple stores.

 What I wonder is:

  1. what kind of indexing schemes can be used to impose structure on the triples in a store?
  2. how can one adapt a B-tree to index each element of a triple rather than just a single primary key – three indexes seems extravagant.
  3. are there quantum algorithms that can beat the best of these schemes?
  4. is there is a place for quantum superposition in a graph matching algorithm (to simultaneously find matching triples then cancel out any that don’t match all the basic graph patterns?)
  5. if DWave’s machines could solve NP-Complete problems, does that mean that we would then just use OWL-Full?
  6. would the speed-ups then be great enough to consider linking everyday app data to large scale-upper ontologies?
  7. is a contradiction in a ‘quantum reasoner’ (i.e. a reasoner that uses a quantum search engine) something that can never occur because it just cancels out and never appears in the returned triples? Would any returned conclusion be necessarily true (relative to the axioms of the ontology?)

Any thoughts?

UPDATE
DWave are now working with Google to help them improve some of their machine learning algorithms. I wonder whether there will be other research into the practicality of using DWave quantum computing systems in conjunction with inference engines? This could, of course, open up whole new vistas of services that could be provided by Google (or their competitors). Either way, it gives me a warm feeling to know that every time I do a search, I’m getting the results from a quantum computer (no matter how indirectly). Nice.

Ubuntist deviant atones for sins

Some time back I wrote  a quote of the day: There is no greater joy than soaring high on the wings of your dreams, except maybe the joy of watching a dreamer who has nowhere to land but in the ocean of reality. For a moment I though the quote was apropos for Alec Clew’s announcement of his apostasy, but after a moment’s reflection I realize that it’s not.

Alec wrote the other day that, due to driver problems, he was thinking that he may have to depart the sunlit pastures of Gnu/Linux to return to the dreary halls of Windows XP. If you’ve noticed any of the censure I’ve directed towards Alec’s perverse habits (disgusting admissions of Ubuntism and flagrantly exhibitionist open-sourcism) over the last year, then you might think that there would be a spiteful little gleam in my eye. But I have admit I’m saddened. We are nearly at a point where we can perform painless .NET development entirely within a Gnu/Linux environment. It would be a sad thing if that were not possible because of hardware support shortcomings, rather than the quality of the toolset (which should be the only deciding factor).

GroupJoins in LINQ

OWL defines two types of property: DatatypeProperty and ObjectProperty. An object property links instances from two Classes, just like a reference in .NET between two objects. In OWL you define it like this:

<owl:ObjectProperty rdf:ID=”isOnAlbum”>
  <rdfs:domain rdf:resource=”#Track”/>
  <rdfs:range rdf:resource=”#Album”/>
</owl:ObjectProperty>

A DatatypeProperty is similar to a .NET property that stores some kind of primitive type like a string or an int. In OWL it looks like this:

<owl:DatatypeProperty rdf:ID=”fileLocation”>
  <rdfs:domain rdf:resource=”#Track” />   
  <rdfs:range  rdf:resource=”&xsd;string”/>
</owl:DatatypeProperty>

The format is very much the same, but the task of querying for primitive types in LINQ and SPARQL is easy compared to performing a one to many query like a SQL Join. So far, I have confined my efforts to DatatypeProperties, and tried not to think about ObjectProperties too much. But the time of reckoning has come – I’ve not got much else left to do on LinqToRdf except ObjectProperties.

Here’s the kind of LINQ join I plan to implement:

[TestMethod]
public void TestJoin()
{
    TestContext db = new TestContext(CreateSparqlTripleStore());
    var q = from a in db.Album 
            join t in db.Track on a.Name equals t.AlbumName into tracks
            select new Album{Name = a.Name, Tracks = tracks};
    foreach(var album in q){
        Console.WriteLine(album.Name);
        foreach (Track track in album.Tracks)
        {
            Console.WriteLine(track.Title);
        }
    }
}

This uses a GroupJoin to let me collect matching tracks and store them in a temporary variable called tracks. I then insert the tracks into the Tracks property on the album I’m newing up in the projection. I need to come up with a SPARQL equivalent syntax, and convert the expression passed for the join into that. SPARQL is a graph based query language, so I am going to be converting my requests into the usual SPARQL triple format, and then using the details from the NewExpression on the query to work out where to put the data when I get it back.

With the non-join queries I have been testing my query provider on, I have observed that for each syntactical component of the query I was passed an Expression tree, representing its contents. With a GroupJoin, you get one, and it contains everything you need to perform the query. My first quandary is over the process of converting this new expression structure into a format that my existing framework can understand. Below is a snapshot of the expression tree created for the join I showed above.

GroupJoin Expression contents

There are five parameters in the expression:

  1. The query object on the Album. That’s the “a in db.Album” part.
  2. The query object on the Track. The “t in db.Track” part.
  3. A lambda function from an album to its Name.
  4. A lambda function from a track to its AlbumName.
  5. A projection creating a new Album, and assigning the tracks collected to the Tracks collection on the newly created Album.

Parameters 1 & 2 are LinqToRdf queries that don’t need to be parsed and converted. I can’t just ask them to render a query for me, since they don’t have any information of value to offer me other than the OriginalType that they were created with. They have received no expressions filtering the kind of data that they return, and they’ll never have their results enumerated. These query objects are just a kind of clue for the GroupJoin about how to compose the query. They can tell it where the data that it’s looking for is to be found.

Here’s how I would guess the SPARQL query would look:

SELECT ?Name ?Title ?GenreName <snip> 
WHERE {
    _:a a a:Album .
    _:t a a:Track .
    _:a a:name ?Name.
    _:t a:albumName ?Name .
    OPTIONAL {_:t a: ?Title}
    OPTIONAL {_:t a: ?GenreName}
    <snip>
}

We can get the names for blank nodes _:a and _:t from the parameter collections of the GroupJoins parameters 3 and 4 respectively. We know that we will be equating ?Name on _:a and ?Name on _:t since those are the lambda functions provided and that’s the format of the join. The rest of the properties are included in optional sections so that if they are not present it won’t stop the details of the OWL instance coming back. By using

    _:a a:name ?Name.
    _:t a:albumName ?Name .

We achieve the same as equality, since two things that are equal to the same are equal to each other. That restricts the tracks to those that are part of an album at the same time.

I’m not sure yet what I will do about the projection, since there is an intermediate task that needs to be performed: to insert the temporary variable ‘tracks’ into the Album object after it has been instantiated. More on that once I’ve found out more.

Creating A LINQ Query Provider

As promised last time, I have extended the query mechanism of my little application with a LINQ Query Provider. I based my initial design on the method published by Bart De Smet, but have extended that framework, cleaned it up and tied it in with the original object deserialiser for SemWeb (a semantic web library by Joshua Tauberer).

In this post I’ll give you some edited highlights of what was involved. You may recal that last post I provided some unit tests that i was working with. For the sake of initial simplicity (and to make it easy to produce queries with SemWeb’s GraphMatch algorithm) I restricted my query language to make use of Conjunction, and Equality. here’s the unit test that I worked with to drive the development process. What I produced last time was a simple scanner that went through my podcasts extracting metadata and creating objects of type Track.

[TestMethod]
public void QueryWithProjection()
{
CreateMemoryStore();
IRdfQuery<Track> qry = new RdfContext(store).ForType<Track>();
var q = from t in qry
where t.Year == 2006 &&
t.GenreName == "History 5 | Fall 2006 | UC Berkeley"
select new {t.Title, t.FileLocation};
foreach(var track in q){
Trace.WriteLine(track.Title + ": " + track.FileLocation);
}
}

This method queries the Tracks collection in an in-memory triple store loaded from a file in N3 format. It searches for any UC Berkley pod-casts produced in 2006, and performs a projection to create a new anonymous type containing the title and location of the files.

I took a leaf from the book of LINQ to SQL to crate the query object. In LINQ to SQL you indicate the type you are working with using a Table<T> class. In my query context class, you identify the type you are working with using a ForType<T>() method. this method instantiates a query object for you, and (in future) will act as an object registry to keep track of object updates.

The RDFContext class is very simple:

public class RdfContext : IRdfContext
{
public Store Store
{
get { return store; }
set { store = value; }
}
protected Store store;
public RdfContext(Store store)
{
this.store = store;
}
public void AcceptChanges()
{
throw new NotImplementedException();
}
public IRdfQuery<T> ForType<T>()
{
return new RdfN3Query<T>(store);
}
}

As you can see, it is pretty bare at the moment. It maintains a reference to the store, and instantiates query objects for you. But in future this would be the place to create transactional support, and perhaps maintain connections to triple stores. By and large, though, this class will be pretty simple in comparison to the query class that is to follow.

I won’t repeat all of what Bart De Smet said in his excellent series of articles on the production of LINQ to LDAP. I’ll confine myself to this implementation, and how it works. So we have to start by creating our Query Object:

public class RdfN3Query<T> : IRdfQuery<T>
{
public RdfN3Query(Store store)
{
this.store = store;
this.originalType = typeof (T);
parser = new ExpressionNodeParser<T>();
}

First it stores a reference to the triple store for later use. In a more real world implementation this might be a URL or connection string. But for the sake of this implementation, we can be happy with the Memory Store that is used in the unit test. next we keep a record of the original type that is being queried against. this is important because later on you may also be dealing with a new anonymous type that will be created by the projection. This will not have any of the Owl*Attribute classes with which to work out URLs for properties and to perform deserialisation.

The two most important methods in IQueryable<T> are CreateQuery and GetEnumerable. CreateQuery is the place where LINQ feeds you the expression tree that it has built from your initial query. You must parse this expression tree and store the resultant query somewhere for later use. I created a string called query to keep that in, and created a class called ExpressionNodeParser to walk the expression tree to build tyhe query string. This is equivalent to the stage where the SQL SELECT query gets created in DLINQ. My CreateQuery looks like this:

public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
RdfN3Query<TElement> newQuery = new RdfN3Query<TElement>(store);
newQuery.OriginalType = originalType;
newQuery.Project = project;
newQuery.Properties = properties;
newQuery.Query = Query;
newQuery.Logger = logger;
newQuery.Parser = new ExpressionNodeParser<TElement>(new
StringBuilder(parser.StringBuilder.ToString()));
MethodCallExpression call = expression as MethodCallExpression;
if (call != null)
{
switch (call.Method.Name)
{
case "Where":
Log("Processing the where expression");
newQuery.BuildQuery(call.Parameters[1]);
break;
case "Select":
Log("Processing the select expression");
newQuery.BuildProjection(call);
break;
}
}
return newQuery;
}

You create new query because you may be doing a projection, in which case the type you are enumerating over will not be the original type that you put into ForType<T>(). Instead it may be the anonymous type from the projection. You transfer the vital information over to the new Query object, and then handle the expression that has been passed in. I am handling two methods here: Where and Select. There are others I could handle, such as OrderBy or Take, but that will have to be for a future post.

Where is the part where the expression representing the query is passed in. Select is passed the tree representing the projection (if there is one). The work is passed off to BuildQuery and BuildProjection accordingly. these names were gratefully stolen from LINQ to LDAP.

BuildQuery in LINQ to LDAP is a fairly complicated affair, but in LINQ to RDF I have paired it right downb to the bone.

private void BuildQuery(Expression q)
{
StringBuilder sb = new StringBuilder();
ParseQuery(q, sb);
Query = Parser.StringBuilder.ToString();
Trace.WriteLine(Query);
}

We create a StringBuilder that can be passed down into the recursive descent tree walker to gather the fragments of the query as each expression gets parsed. the result is then stored in the Query property of the Query object. BuildProjection looks like this:

private void BuildProjection(Expression expression)
{
LambdaExpression le = ((MethodCallExpression)expression).Parameters[1] as
LambdaExpression;
if (le == null)
throw new ApplicationException("Incompatible expression type found when building a projection");
project = le.Compile();
MemberInitExpression mie = le.Body as MemberInitExpression;
if (mie != null)
foreach (Binding b in mie.Bindings)
FindProperties(b);
else
foreach (PropertyInfo i in originalType.GetProperties())
properties.Add(i.Name, null);
}

Much of it is taken directly from LINQ to LDAP. I have adapted it slightly because I am targeting the May 2007 CTP of LINQ. I’ve done this only because I have to use VS 2005 during the day, so I can’t use the March 2007 version of Orcas.

ParseQuery is used by BuildQuery to handle the walking of the expression tree. Again that is very simple since most of the work is now done in ExpressionNodeParser. It looks like this:

private void ParseQuery(Expression expression, StringBuilder sb)
{
Parser.Dispatch(expression);
}

Parser.Dispatch is a gigantic switch statement that passes off the expression tree to handler methods:

public void Dispatch(Expression expression)
{
switch (expression.NodeType)
{
case ExpressionType.Add:
Add(expression);
break;
case ExpressionType.AddChecked:
AddChecked(expression);
break;
case ExpressionType.And:
And(expression);
break;
case ExpressionType.AndAlso:
AndAlso(expression);
//...

Each handler method then handles the root of the expression tree, breaking it up and passing on what it can’t handle itself. For example, the method AndAlso just takes the left and right side of the operator and recursively dispatches them:

public void AndAlso(Expression e)
{
BinaryExpression be = e as BinaryExpression;
if (be != null)
{
Dispatch(be.Left);
Dispatch(be.Right);
}
}

The equality operator is the only operator that currently gets any special effort.

public void EQ(Expression e)
{
BinaryExpression be = e as BinaryExpression;
if (be != null)
{
MemberExpression me = be.Left as MemberExpression;
ConstantExpression ce = be.Right as ConstantExpression;
QueryAppend(tripleFormatStringLiteral,
InstancePlaceholderName,
OwlClassSupertype.GetPropertyUri(typeof(T),
me.Member.Name),
ce.Value.ToString());
}
MethodCallExpression mce = e as MethodCallExpression;
if (mce != null && mce.Method.Name == "op_Equality")
{
MemberExpression me = mce.Parameters[0] as MemberExpression;
ConstantExpression ce = mce.Parameters[1] as ConstantExpression;
QueryAppend(tripleFormatStringLiteral,
InstancePlaceholderName,
OwlClassSupertype.GetPropertyUri(typeof(T),
me.Member.Name),
ce.Value.ToString());
}
}

The equality expression can be formed either through the use of a binary expression with NodeType.EQ or as a MethodCallExpression on op_Equality for type string. If the handler for the MethodCallExpression spots op_Equality it passes the expression off to the EQ method for it to render instead. EQ therefore needs to spot which type of Node it’s dealing with to know how to get the left and right sides of the operation. In a BinaryExpression there are Right and Left properties, whereas in a MethodCallExpression these will be found in a Parameters collection. In our example they get the same treatment.

You’ll note that we assume that the left operand is a MemberExpression and the right is a ConstantExpression. That allows us to form clauses like this:

where t.Year == 2006

but it would fail on all of the following:

where t.Name.ToUpper() == "SOME STRING"
where t.Name == t.Other
where t.Year.ToString() == "2006"

Each of these cases will have to be handled individually, so the number of cases we need to handle can grow. As Bart De Smet pointed out, some of the operations might have to be performed after retrieval of the results since semantic web query languages are unlikely to have complex string manipulation and arithmetic functions. Or at least, not yet.

The QueryAppend forms an N3 Triple out of its parameters and appends it to the StringBuilder that was passed to the Parser initially. At the end of the recursive tree walk, this string builder is harvested and preprocessed to make it ready to pass to the triple store. In my previous post I described an ObjectDeserialisationsSink that was passed to SemWeb during the query process to harvest the results. This has been reused to gather the results of the query from within our query.

I mentioned earlier that the GetEnumerator method was important to IQueryable. An IQueryable is a class that can defer execution of its query till someone attempts to enumerate its results. Since that’s done using GetEnumerator the query must be performed in GetEnumerator. My implementation of GetEnumerator looks like this:

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
if (result != null)
return result.GetEnumerator();
query = ConstructQuery();
PrepareQueryAndConnection();
PresentQuery(query);
return result.GetEnumerator();
}

result is the List<TElement> variable where I cache the results for later use. What that means is that the query only gets run once. Next time the GetEnumerator gets called, result is returned directly. This reduces the cost of repeatedly enumerating the same query. Currently the methods ConstructQuery, PrepareQueryAndConnection, and PresentQuery are all fairly simple affairs that exist more as placeholders so that I can reuse much of this code for a LINQ to SPARQL implementation that is to follow.

As you’ve probably worked out, there is a huge amount of detail that has to be attended to, but the basic concepts are simple. the reason why more people haven’t written LINQ query providers before now is simply that fact that there is no documentation about how to do it. When you try though, you may find it easier than you thought.

There is a great deal more to do to LINQ to RDF before something it is ready for production use, but as a proof of concept that semantic web technologies can be brought into the mainstream it serves well. Thereason why we use ORM systems such as LINQ to SQL is to help us overcome the Impedance Mismatch that exists between the object and relational domains. An equally large mismatch exists between the Object and Semantic domains. tools like LINQ to RDF will have to overcome the mismatch in order for them to be used outside of basic domain models.

Using RDF and C# to create an MP3 Manager – Part 3

Last time I hurriedly showed you how you can perform the next step of converting a triple store into an ORM system of sorts. The purpose of all this activity, and the reason I left off blogging about LINQ was that I am working on a system to allow me to use LINQ with a triple store and reasoner. The benefit of doing so is that we should have a lot of the benefits of the modern relational world with the power and connectivity of the new world of the semantic web. In this post I shall outline the steps required to start working with LINQ to RDF (as I’ve chosen to call it through lack of imagination).

I’ve been using test driven development throughout, so I already have a few ‘integration’ unit tests to show you:

[TestMethod]
public void Query()
{
  string urlToRemoteSparqlEndpoint = "http://localhost/MyMusicService/SparqlQuery.ashx";
  RdfContext<Track> ctx = new RdfSparqlContext<Track>(urlToRemoteSparqlEndpoint);
  var titles = from t in ctx
    where t.Year > 1998 &&
    t.GenreName == "Ambient Techno" ||
    t.GenreName == "Chillout"
    select t.Title;
  foreach(string title in titles)
    Console.WriteLine(title);
}

In English, this means that rather than manipulating a local triple store, I want the RdfSparqlContext to compose a SPARQL query and present it to the query endpoint found at location urlToRemoteSparqlEndpoint. I then want it to deserialise the results returned and store them in titles. This is a nice mixture of new features from .NET 3.5, combined with some of the features I’ve already developed for object deserialisation.

With the example above I am concerned more with the querying aspect of LINQ (it being a query language n’ all!) but that is not much use to me in the world of transactional web development where I find myself mired for the moment, so we need full CRUD behaviour from this system. Here’s a unit test for object update.

[TestMethod]
public void Update()
{
  string urlToRemoteSparqlEndpoint = @"http://localhost/MyMusicService/SparqlQuery.ashx";
  RdfContext<Track> ctx = new RdfSparqlContext<Track>(urlToRemoteSparqlEndpoint);
  var q = from t in ctx
    where t.Year > 1998 &&
    t.GenreName == "Ambient Techno" ||
    t.GenreName == "Chillout"
    select t;
  foreach (Track t in q)
    t.Rating = 5;
  ctx.AcceptChanges();
}

Here, I’m getting a bunch of objects back from the triple store, modifying their Rating property and then asking for those changes to be stored. This follows the usage patterns for LINQ to SQL.

To satisfy these unit tests (plus ones for the rest of the CRUD behaviour and with support for N3, in-memory and RDBMS based local triple stores is what I’m aiming to complete – eventually. Here’s the general scheme for implementing querying using LINQ. It assumes that RDF data structures are taken unmodified from the SemWeb library.

  • Create a Query Object (I guess this would be our RdfContext class above)
  • Implement IQueryable<T> on it.
  • When the enumerable is requested, convert the stored expression tree into the target language
  • Present it to whatever store or endpoint is available,
  • Deserialise the results into objects
  • Yield the results (probably as they are being deserialised)

This is a very broad outline of the tasks. I’ll explain in a lot more depth in subsequent posts, as I tackle each step.

Using RDF and C# to create an MP3 Manager – Part 2

I’ve been off the air for a week or two – I’ve been hard at work on the final stages of a project at work that will go live next week. I’ve been on this project for almost 6 months now, and next week I’ll get a well earned rest. What that means is I get to do some dedicated Professional Development (PD) time which I have opted to devote to Semantic Web technologies. That was a hard sell to the folks at Readify, what with Silverlight and .NET 3 there to be worked on. I think I persuaded them that consultancies without SW skills will be at a disadvantage in years to come.

Anyway, enough of that – onto the subject of the post, which is the next stage of my mini-series about using semantic web technologies in the production of a little MP3 file manager.

At the end of the last post we had a simple mechanism for serialising objects into a triple store, with a set of services for extracting relevant information out of an object, and to tie it to predicates defined in on ontology. In this post I will show you the other end of the process. We need to be able to query against the triple store and get a collection of objects back.

The query I’ll show you is very simple, since the main task for this post is object deserialisation, once we can shuttle objects in and out of the triple store then we can focus on beefing up the query process.

Querying the triple store

For this example I just got a list of artists for the user and allowed them to select one. That artist was then fed into a graph match query in SemWeb, to bring back all of the tracks whose artist matches the one chosen.

The query works in the usual way – get a connection to the data store, create a query, present it and reap the result for conversion to objects:

private IList<Track> DoSearch()
{
  MemoryStore ms = Store.TripleStore;
  ObjectDeserialiserQuerySink<Track> sink = new ObjectDeserialiserQuerySink<Track>();
  string qry = CreateQueryForArtist(artists[0].Trim());
  Query query = new GraphMatch(new N3Reader(new StringReader(qry)));
  query.Run(ms, sink);
  return tracksFound = sink.DeserialisedObjects;
}

We’ll get on the the ObjectDeserialiserQuerySink in a short while. The process of creating the query is really easy, given the simple reflection facilities I created last time. I’m using the N3 format for the queries, for the sake of simplicity – we could just as easily used SPARQL. We start with a prefix string to give us a namespace to work with, we then enumerate the persistent properties of the Track type. For each property we then insert a triple meaning “whatever track is select – get its property as well”. Lastly, we add the artist name ass a known fact, allowing us to specify exactly what tracks we were talking about.

private static string CreateQueryForArtist(string artistName)
{
  string queryFmt = "@prefix m: <http: aabs.purl.org/ontologies/2007/04/music#> .\n";
  foreach (PropertyInfo info in OwlClassSupertype.GetAllPersistentProperties(typeof(Track)))
  {
    queryFmt += string.Format("?track <{0}> ?{1} .\n", OwlClassSupertype.GetPropertyUri(typeof(Track), info.Name), info.Name);
  }
  queryFmt += string.Format("?track <{0}> \"{1}\" .\n", OwlClassSupertype.GetPropertyUri(typeof(Track), "ArtistName"), artistName);
  return queryFmt;
}

Having created a string representation of the query we’re after we pass it to a GraphMatch object, which is a kind of query were you specify a graph that is a kind of prototype for the structure of the results desired. I also created a simple class called ObjectDeserialiserQuerySink:

public class ObjectDeserialiserQuerySink<T> : QueryResultSink where T : OwlClassSupertype, new()
{
  public List<T> DeserialisedObjects
  {
  get { return deserialisedObjects; }
  }
  private List<T> deserialisedObjects = new List<T>();
  public ObjectDeserialiserQuerySink()
  {
  }
  public override bool Add(VariableBindings result)
  {
    T t = new T();
    foreach (PropertyInfo pi in OwlClassSupertype.GetAllPersistentProperties(typeof(T)))
    {
      try
      {
        string vn = OwlClassSupertype.GetPropertyUri(typeof (T), pi.Name).Split('#')[1];
        string vVal = result[pi.Name].ToString();
        pi.SetValue(t, Convert.ChangeType(vVal, pi.PropertyType), null);
      }
      catch (Exception e)
      {
        Debug.WriteLine(e);
        return false;
      }
    }
    DeserialisedObjects.Add(t);
    return true;
  }
}

For each match that the reasoner is able to find, a call gets made to the Add method of the deserialiser with a set of VariableBindings. Each of the variable bindings corresponds to solutions of the free variables defined in the query. Since we generated the query out of the persistent properties on the Track type the free variables matched will also correspond to the persistent properties of the type. What that means is that it is a straightforward job to deserialise a set of VariableBindings into an object.

That’s it. We now have a simple triple store that we can serialise objects into and out of, with an easy persistence mechanism. But there’s a lot more that we need to do. Of the full CRUD behaviour I have implemented Create and Retrieve. That leave Update and Delete. As we saw in one of my previous posts, that will be a mainly manual programmatical task since semantic web ontologies are to a certain extend static. What that means is that they model a domain as a never changing body of knowledge about which we may deduce more facts, but where we can’t unmake (delete) knowledge.

The static nature of ontologies seems like a bit of handicap to one who deals more often than not with transactional data – since it means we need more than one mechanism for dealing with data – deductive reasoningh, and transactional processing. With the examples I have given up till now I have been dealing with in-memory triple stores where the SemWeb API is the only easy means of updating and deleting data. When we are dealing with a relational database as our triple store, we will have the option to exploit SQL as another tool for managing data.

Powered by ScribeFire.

New Features in Visual Studio Orcas

I’ve been taking the new Visual Studio Preview for a spin, and it’s got some pretty nice new additions. These aren’t just the headline features that have been publicized elsewhere, but the thoughtful additions to usability that will make our lives a little bit easier. They should also help us to make our code a lot cleaner and less complex. We see the introduction of easy performance reporting and differential comparison of profiling sessions. We also see the introduction of code metrics analysis. The March 2007 CTP also sees the long awaited intellisense support for LINQ in C# as well as some other nice features for exporting code and projects as templates.

The performance report comes with a single click. It helps you to target your optimizations.

After you’ve done your optimizations, you can rerun your profiler and do a comparison to see how well your efforts worked.

The code analysis tools now offer code complexity metrics that will indicate whether your code needs simplification or refactoring.

The refactoring tools have not received much attention, and still lag behind the likes of R#. There are a quite a few refactoring code snippets, that may allow us to craft our own refactorings. If so, then we have a power that has not been seen outside of UML tools like Rational XDE.

The tools for architects have come along way. It’s clear that they are targeting the aims of the Dynamic Systems Initiative (DSI). This is a very exciting piece of work, and will revolutionize development when it reaches fruition. Here you can see an Application diagram with a set of property pages allowing the architect to define the system properties required for deployment of a windows application called Test1.

The class diagram now allows you to directly enter your method definitions in the class details pane. Code is generated on the fly in the code window. I’m not sure if this is new, but I can’t recall seeing anything like this in 2005.

While you’re editing the properties of your methods, you can also directly edit the code commentary as well. Now there’s no excuse…

There is a new feature allowing you to search for web services defined in other projects, to insert them as web references in the current project. Great productivity feature for distributed applications.

The class view pane gets a new search box that allows you to search for classes fields and properties. This is really useful, and can save programmers hours of hunting on large projects. (provided they haven’t got R# of course)

Yes! LINQ intellisense. Nuff said.

Orcas also introduces a nice Export template feature that allows you to develop a project or group of classes for exporting as a new item template. This feature is a great way to allow architects to ease the development cycle. They can produce pieces of reference code and distribute them to the rest of their development team.

Just select the classes that you want to export.

Give an explanation of what they are intended to do.

And visual studio goes through them creating placeholders for class and namespace identifiers. These can then be filled in when the developer creates a new item.

there are still problems that need to be sorted out though. Like project properties…

These are a few of the things that I noticed immediately. I’m sure there are more to come. The documentation has not been overhawled much, and the LINQ section is still mostly empty pages. But my initial impression is that Orcas is going to be a delight to work with, for the whole team.

PowerShell NOT inferior to Cygwin

In a previous post, I kinda outed myself as a lover of “find | xargs” and grep. It seems that I inadvertantly gave offence to Jeffrey Snover (the architect of powershell), for whom I have great respect. So I thought I ought to set the record straight.

I like powershell a lot, and I suspect that it was familiarity with Unix that drove me back to Cygwin. I was truly inspired by the Channel9 interview that Jeffrey Snover gave. I had a few problems with the way that Cygwin handled NT file security settings, that caused me no end of grief. So I was more than happy to take powershell for a spin.  I think the idea of having an object pipeline is serendipitous, and I particularly like the fact that I am dealing with the .NET framework. I’ve been working with that for years so I don’t have a huge learning curve to ascend in that regard.

Funnily enough, the reason I struggled is apropos to what I was discussing in the original post – a relative lack of documentation. I like to be able to read around a topic. To get a lot of people’s ideas. I initially found it hard to get started – I didn’t have a sense, at times, of the capabilities of powershell, and where I should turn to for things that I knew how to do in bash. I was tryinig out the beta version of monad which was a while back, so things may have changed. I have to try again.

Another reason why I opted to go back to cygwin - I get pretty much all of the mainstream Gnu utilities for free. It didn’t occur to me that with a little fiddling I could have the best of both worlds by accessing Cygwin from within powershell. I haven’t tried it yet, but once I have, I shall report back with instructions.

Photosynth CTP now on display

Live Labs has now put Photosynth on display to the public. You can’t add your own photos yet, but the interface is everything that they promised. I can’t wait to be able to use this on my own photos.

I think it will change the way I use my camera. With this interface I will still have to compose pictures that stand alone, since each picture is rendered alone on the screen. But I will be much more inclined to randomly shoot around me to try to ensure I have an overlapping montage ready for when photosynth is available on the desktop (assuming it will be). Currently it is only available as an ActiveX control for use in a browser. Does that mean that the control is to link you to images stored centrally? Is this the product that MS hopes will draw people away from Flickr to a service of their own? I hope not. I want this to replace Canon ZoomBrowser EX as the way I get to my images in future.