SemMF - A Semantic Matching Framework

Traversing the Matching Result

Radoslaw Oldakowski
November 2006

 

In the prevous tutorial we have created a matching description for a simple job matching scenario. Now we will continue with starting the engine and subsequently traversing its matching result.

First, we include SemMF class MatchingEngine and package result.* as well as some java.util classes

import de.fuberlin.wiwiss.semmf.engine.MatchingEngine;
import de.fuberlin.wiwiss.semmf.result.*;

import java.util.Iterator;
import java.util.List;

To peform a matching operation for our use case all we need to do is to create a new instance of MatchingEngine, by passing the URL of our previously created matching description, and to call the method exec()

MatchingEngine me = new MatchingEngine("file:doc/examples/jobMD.n3", "N3");
MatchingResult mr = me.exec();

The engine returns a MatchingResult object holding a ranked list of detailed matching results (instances of GraphMatchingResult) for each of our job candidates. It provides methods for interating over the ranking and for (re-)sorting the list either by overall similarity or by each cluster similarity. See the class reference for further details.

Now, we will traverse the matching output in order to print it out. First we access the Resource representing our job posting and retrieve its URI:

System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
System.out.println("Query Graph: " + mr.getFirst().getQueryGraphEntryNode().getURI());
System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r");

Next, we iterate over all GraphMatchingResults and for each of them we retrieve, using methods provided by this interface, the URI of a Resourcre representing a job seeker and his overall similarity with our job posting:

while (mr.hasNext()) {
			
	GraphMatchingResult gmr = mr.next();
						
	System.out.println("\r===========================================================");
	System.out.println("Res Graph : " + gmr.getResGraphEntryNode().getURI());
	System.out.println("Sim       : " + gmr.getSimilarity());
	System.out.println("===========================================================\r");

In addition, each GraphMatchingResult holds a list of matching results for every cluster we have specified in our matching description. They are represented by instances of ClusterMatchingResut. So, we iterate over this list and retrieve the label, similarity score, and weight value for each cluster:

	List clusterList = gmr.getClusterMatchingResultList();
	for (Iterator itC = clusterList.iterator(); itC.hasNext();) {
		
		ClusterMatchingResult cmr = (ClusterMatchingResult) itC.next();
		
		System.out.println("-------------------------------------------");
		System.out.println("Cluster label : " + cmr.getLabel());
		System.out.println("Cluster sim   : " + cmr.getSimilarity());
		System.out.println("Cluster weight: " + cmr.getWeight());

Then its goes one level deeper like in a matching description. That means each ClusterMatchingResult holds a list of matching results for all nodes inside this cluster. Once again, we iterate over this list containing instances of NodeMatchingResult und by using its methods we access the RDFNodes representing properties of objects from our scenario (job posting and candidates) as well as their similarity and weight:

		List nodeList = cmr.getNodeMatchingResultList();
			
			for (Iterator itN = nodeList.iterator(); itN.hasNext();) {
					
				NodeMatchingResult nmr = (NodeMatchingResult) itN.next();
					
				List propertyList = nmr.getPropertyMatchingResultList();
										
				System.out.println("    - - - - - - - - - - - - - - - - - - --");
				System.out.println("    Node label : " + nmr.getLabel());					
				if (propertyList.isEmpty()) {
					System.out.println("    query node : " + nmr.getQueryNode().toString());
					System.out.println("    res node   : " + nmr.getResNode().toString());									
				}
				System.out.println("    Node sim   : " + nmr.getSimilarity());
				System.out.println("    Node weight: " + nmr.getWeight());

Note that, for nodes which are Blank Nodes and were accordingly specified in our matching description (i.e. skill node), we have to go even deeper and iterate over the list of matching results for RDF properties hanging from those nodes. These are represented by instances of PropertyMatchingResult for each of which we retrieve the RDFNodes representing properties of objects from our scenario (job posting and candidates) as well as their similarity score and associated weight.

				for (Iterator itP = propertyList.iterator(); itP.hasNext();) {
					
					PropertyMatchingResult pmr = (PropertyMatchingResult) itP.next();
					
					System.out.println("        . . . . . . . . . . . . . . . . . ");
					System.out.println("        prop label : " + pmr.getLabel());
					System.out.println("        query prop : " + pmr.getQueryPropVal().toString());
					System.out.println("        res prop   : " + pmr.getResPropVal().toString());			
					System.out.println("        prop sim   : " + pmr.getSimilarity());
					System.out.println("        prop weight: " + pmr.getWeight());					
				}			
			}				
		}		
}

You can find the full working code for this tutorial in de.fuberlin.wiwiss.semmf.examples.JobMatching.java.

In you run the code it will produce an output like this (below only the matching result for the best ranked candidate):

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
Query Graph: http://example.org/JobPositionPosting.rdfs#JPP_1
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$


===========================================================
Res Graph : http://example.org/JobPositionSeeker.rdfs#JPS_1
Sim       : 0.93250006
===========================================================

-------------------------------------------
Cluster label : job details
Cluster sim   : 0.93
Cluster weight: 0.25
    - - - - - - - - - - - - - - - - - - --
    Node label : travel required
    query node : false
    res node   : false
    Node sim   : 1.0
    Node weight: 0.3
    - - - - - - - - - - - - - - - - - - --
    Node label : salary
    query node : 40000
    res node   : 41000
    Node sim   : 0.9
    Node weight: 0.7
-------------------------------------------
Cluster label : skills
Cluster sim   : 0.9333334
Cluster weight: 0.75
    - - - - - - - - - - - - - - - - - - --
    Node label : skill node
    Node sim   : 1.0
    Node weight: 0.33333334
        . . . . . . . . . . . . . . . . . 
        prop label : skill
        query prop : http://example.org/it-skills.rdfs#Relational_databases
        res prop   : http://example.org/it-skills.rdfs#Oracle
        prop sim   : 1.0
        prop weight: 0.8
        . . . . . . . . . . . . . . . . . 
        prop label : skill level
        query prop : http://example.org/it-skills.rdfs#Intermediate
        res prop   : http://example.org/it-skills.rdfs#Advanced
        prop sim   : 1.0
        prop weight: 0.2
    - - - - - - - - - - - - - - - - - - --
    Node label : skill node
    Node sim   : 0.8
    Node weight: 0.33333334
        . . . . . . . . . . . . . . . . . 
        prop label : skill
        query prop : http://example.org/it-skills.rdfs#JavaScript
        res prop   : http://example.org/it-skills.rdfs#PHP
        prop sim   : 0.875
        prop weight: 0.8
        . . . . . . . . . . . . . . . . . 
        prop label : skill level
        query prop : http://example.org/it-skills.rdfs#Expert
        res prop   : http://example.org/it-skills.rdfs#Intermediate
        prop sim   : 0.5
        prop weight: 0.2
    - - - - - - - - - - - - - - - - - - --
    Node label : skill node
    Node sim   : 1.0
    Node weight: 0.33333334
        . . . . . . . . . . . . . . . . . 
        prop label : skill
        query prop : http://example.org/it-skills.rdfs#Java
        res prop   : http://example.org/it-skills.rdfs#Java
        prop sim   : 1.0
        prop weight: 0.8
        . . . . . . . . . . . . . . . . . 
        prop label : skill level
        query prop : http://example.org/it-skills.rdfs#Advanced
        res prop   : http://example.org/it-skills.rdfs#Expert
        prop sim   : 1.0
        prop weight: 0.2

 


see next: How to Implement New Matchers