Child pages
  • Practical Java Algorithm Development

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

On the second Algorithm Properties page we'll be doing something new, which requires a bit of explanation. in_data for a CIShell algorithm can be either files or Java objects. in_data for files is in the form of a MIME type, like "file:text/nwb" for the Network Workbench network format. in_data for Java objects is the class name of the object, such as prefuse.data.Graph for the prefuse Graph object. For this tutorial we will be using the data type "edu.uci.ics.jung.graph.Graph", which is the full class name for the Graph object in the Jung graph library. You should also check the checkbox for "On the menu", and set the menu path to be "Analysis". Image Added
Figure 1: Setting the input and output data type.

To make our Attack Tolerance algorithm more flexible, we would like to allow our users to choose how many of the highest degree nodes they wish to remove. On the Algorithm Parameters page, click "Add...". Set Unique ID to "numNodesToDelete", Name to "Number of Nodes to Delete", Description to "The number of highest degree nodes to delete from the input graph", Default Value to "1", and Input Type to "Integer". Click OK to finish adding this parameter. This will create a field in the user-input parameters GUI which will appear whenever a user runs our Attack Tolerance algorithm. Later we'll show you how to access these values from the AttackToleranceAlgorithm class. Image Added
Figure 2: Setting the algorithm parameters to allow user interaction.

Now we have finished creating the supporting files for our plugin, and are ready to begin writing code.

...

Because we specified the Jung graph as the in_data type, CIShell will arrange for us to be given a Jung graph object when this algorithm is run (if a network in the Data Manager is of some other type, CIShell's conversion service will convert that network to a Jung graph). The input objects are held in the data array that is passed as a constructor to the algorithm. We use the following code to access the Jung graph in this array.

Code Block


public Data\[\] execute() throws AlgorithmExecutionException {
        Graph graph = (Graph)(data[0].getData());
    	return null;
    }

...

To make the JUNG packages available to our plugin, double-click on META-INF/MANIFEST.MF in your attacktolerance plugin, and click the "Dependencies" tab at the bottom of the Manifest's window. You should see something like this: Image Added
Figure 3: Manifest dependencies.
Notice that under "Import Packages" several packages are already listed. The CIShell algorithm wizard automatically imports several core CIShell packages.

To import the Jung packages, click "Add...". A dialog box that looks like this should appear: Image Added
Figure 4: Importing the Jung packages.

to find all packages with the word "jung" in your workspace, type "jung" in the "Export Packages:" field. All the JUNG packages exported from the plugin we downloaded earlier should now be shown. To select all the packages, click the top-most package, then hold down the Shift key and select the bottom-most package (This should highlight all of the packages). Click "Ok" to finish our selection.

To see the result of this operation, click the "MANIFEST.MF" tab at the bottom of the Manifest's window. You should see something like this: Image Added
Figure 5: The MANIFEST.MF file.

The packages we have added now appear as part of the "Import-Package" attribute. It is possible to edit this file directly, but it is easier and safer to use the automatic method, as we just did.

...

The following line is used to extract the number of nodes we should delete, "numNodesToDelete" from the Dictionary. int numNodesToDelete = ((Integer) parameters.get("numNodesToDelete")).intValue();
Now we have obtain everything we need to do the attack tolerance analysis. Since the specifics of this algorithm are not important to learning about CIShell, I have provided the core code in the class below:

Code Block


AttackTolerance:package org.my.attacktolerance;

import java.util.Iterator;

import edu.uci.ics.jung.algorithms.importance.DegreeDistributionRanker;
import edu.uci.ics.jung.algorithms.importance.NodeRanking;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.Vertex;

public class AttackTolerance {

/*\*
* Perform an attack tolerance test on the graph.
\*
* @return a Graph with 'numNodesToDelete' of its highest degree nodes deleted.
* Edges associated with deleted nodes will be removed as well.
\*/
public static Graph testAttackTolerance(final Graph graph, int numNodesToDelete) {

Graph graphToAttack = (Graph) graph.copy();

DegreeDistributionRanker rankByDegree = new  DegreeDistributionRanker(graphToAttack);
rankByDegree.evaluate();

Iterator nodesByDegree = rankByDegree.getRankings().iterator();
for (int numNodesDeleted = 0;
numNodesDeleted < numNodesToDelete && nodesByDegree.hasNext();
numNodesDeleted++) {

			Vertex v = ((NodeRanking) nodesByDegree.next()).vertex;

			graphToAttack.removeVertex(v);
		}

return graphToAttack;
}
}

...

Below is the updated code for AttackToleranceAlgorithm, which now utilizes the AttackTolerance class, and returns the modified graph as Data:package org.my.attacktolerance;

Code Block


import java.util.Dictionary;

import org.cishell.framework.CIShellContext;
import org.cishell.framework.algorithm.Algorithm;
import org.cishell.framework.data.BasicData;
import org.cishell.framework.data.Data;
import org.cishell.framework.data.DataProperty;

import edu.uci.ics.jung.graph.Graph;

public class AttackToleranceAlgorithm implements Algorithm {

private Data\[\] data;
private int numNodesToDelete;

public AttackToleranceAlgorithm(Data\[\] data, Dictionary parameters, CIShellContext context) {
		this.data = data;
		this.numNodesToDelete = ((Integer) parameters.get("numNodesToDelete")).intValue();
	}

public Data\[\] execute() {
Graph inputGraph = (Graph) (data[0].getData());

Graph outputGraph = AttackTolerance.testAttackTolerance(inputGraph, numNodesToDelete);

Data outputData = prepareOutputData(outputGraph);

return new Data\[\] { outputData };
}

private Data prepareOutputData(Graph outputGraph) {
		Data outputData = new BasicData(outputGraph, Graph.class.getName());

		Dictionary metadata = outputData.getMetadata();
		metadata.put(DataProperty.PARENT, data[0]);
		metadata.put(DataProperty.TYPE, DataProperty.NETWORK_TYPE);
		metadata.put(DataProperty.LABEL, "High Degree Node Deletion (Attack Tolerance)");

		return outputData;
	}
}

...

Source code for AttackToleranceAlgorithmFactory as a ParameterMutator:package org.my.attacktolerance;

Code Block


import java.util.Dictionary;

import org.cishell.framework.CIShellContext;
import org.cishell.framework.algorithm.Algorithm;
import org.cishell.framework.algorithm.AlgorithmFactory;
import org.cishell.framework.algorithm.ParameterMutator;
import org.cishell.framework.data.Data;
import org.cishell.reference.service.metatype.BasicAttributeDefinition;
import org.cishell.reference.service.metatype.BasicObjectClassDefinition;
import org.osgi.service.metatype.AttributeDefinition;
import org.osgi.service.metatype.ObjectClassDefinition;

import edu.uci.ics.jung.graph.Graph;

public class AttackToleranceAlgorithmFactory implements AlgorithmFactory, ParameterMutator {
public Algorithm createAlgorithm(Data\[\] data, Dictionary parameters, CIShellContext context) {
        return new AttackToleranceAlgorithm(data, parameters, context);
    }

public static final int DELETE_ONE_IN_N_NODES_BY_DEFAULT = 10;

/\*
* set the default value for 'Number of Highest Degree Nodes to Delete'
* to 1/Nth of the total number of nodes in the graph.
\*/
public ObjectClassDefinition mutateParameters(Data\[\] data, ObjectClassDefinition parameters) {

//calculate how many nodes to delete by default

Graph inputGraph = (Graph) data[0].getData();
int defaultNumNodesToDelete = calculateDefaultNumNodesToDelete(inputGraph);

BasicObjectClassDefinition newParameters = new BasicObjectClassDefinition(
parameters.getID(),
parameters.getName(),
parameters.getDescription(), null);


//for each attribute definition in the original attribute parameters
AttributeDefinition\[\] paramAttributes =
parameters.getAttributeDefinitions(ObjectClassDefinition.ALL);
for (int ii = 0; ii < paramAttributes.length; ii++) {
AttributeDefinition paramAttribute = paramAttributes[ii];
//if it is the numNodesToDelete attribute...
if (paramAttribute.getID().equals("numNodesToDelete")) {
				/*
				 * add that attribute to our new set of attributes,
				 *  but with the new default value we calculated
				 */
				AttributeDefinition modifiedAttribute = new BasicAttributeDefinition(
						paramAttribute.getID(), paramAttribute.getName(),
						paramAttribute.getDescription(), paramAttribute.getType(),
						String.valueOf(defaultNumNodesToDelete));
				newParameters.addAttributeDefinition(
						ObjectClassDefinition.REQUIRED, modifiedAttribute);

			} else {
				//add any other attribute to our new set of attributes as-is.
				newParameters.addAttributeDefinition(
						ObjectClassDefinition.REQUIRED, paramAttributes[ii]);
			}
}

//return our new attribute parameters
return newParameters;
}

private int calculateDefaultNumNodesToDelete(Graph graph) {
		int numNodesInGraph = graph.numVertices();
		int recommendedToDelete = Math.max(numNodesInGraph / DELETE_ONE_IN_N_NODES_BY_DEFAULT, 1);
		return recommendedToDelete;
	}
}

...