PGX 19.1.0
Documentation
Note: This feature is only available in the following software packages: PGX on the Oracle Tech Network

Compile and Run Your Own Green-Marl Program

A key benefit of PGX is that you may implement algorithms with no limit. You can easily add your own algorithms using Green-Marl, a domain-specific language designed for graph algorithms. Green-Marl has a C-like syntax. Refer to the Built-in Algorithms section for a number of code example. For a full reference, see the Green-Marl language specification.

'Hello World' program

To start with, we will compile and run a Green-Marl 'Hello World' program.

/*
 * Copyright (C) 2013 - 2019 Oracle and/or its affiliates. All rights reserved.
 */
procedure hello_world() {
  println("Hello World");
}

PGX 19.1.0 limitations

The current version of PGX does not support the print statement in remote mode. Further, it does not support Green-Marl algorithms that use edge properties on undirected graphs.

This program can be found in the examples/gm directory of the distribution.

Creating a session

Let's begin by creating a session:

cd $PGX_HOME
./bin/pgx
// starting the shell will create an implicit session
import oracle.pgx.api.*;

...

PgxSession session = Pgx.createSession("my-session");

Compiling the code

Next, let's compile the 'Hello World' program:

pgx> p = session.compileProgram("examples/gm/hello_world.gm")
==> Compiled Program hello_world
CompiledProgram p = session.compileProgram("examples/gm/hello_world.gm")

Run 'Hello World'

pgx> p.run()
Hello World
==> {
  "success" : true,
  "canceled" : false,
  "executionTimeMs" : 0,
  "exception" : null
}
AnalysisResult<Void> r = p.run();

Graph Analysis Example

As a more advanced example, we will compile the following algorithm, which computes the maximum degree of a given graph:

/*
 * Copyright (C) 2013 - 2019 Oracle and/or its affiliates. All rights reserved.
 */

/*
* Computes the maximum out degree of a graph
*
* Input-Parameters:
* G:    arbitrary graph.
*
* Returns: maximum out degree
*
*/
procedure max_degree(G: graph): int {
  return max(n: G.nodes) { n.degree() };
}

You can find this program in the examples/gm directory of the distribution.

Compiling the code

Compile our max_degree procedure:

pgx> p = session.compileProgram("examples/gm/max_degree.gm")
==> Compiled Program max_degree
CompiledProgram p = session.compileProgram("examples/gm/max_degree.gm")

In PGX, every algorithm is uniquely identified by an analysis name, which equals the procedure name of the given Green-Marl program. If an algorithm with the same name already exists for this session, it will be overwritten. Note: Algorithms are session-bound, meaning session A cannot overwrite any algorithm from session B. Likewise, session A cannot execute algorithms compiled by session B.

Loading the graph data into memory

Our procedure uses a graph as an input argument. In order to run our algorithm, we first need to load a graph into memory. In this tutorial, we will load the sample example graph included in the distribution.

pgx> g = session.readGraphWithProperties("examples/graphs/connections.edge_list.json")
PgxGraph g = session.readGraphWithProperties("examples/graphs/connections.edge_list.json");

Running the algorithm

Next, let's execute our compiled algorithm with our loaded graph as input:

pgx> p.run(g)
==> {
  "success" : true,
  "canceled" : false,
  "returnValue" : 2,
  "executionTimeMs" : 0,
  "exception" : null
}
AnalysisResult<Integer> r = p.run(g);
System.out.println("max_degree = " + r.getReturnValue());

Congratulations, you have successfully executed a custom Green-Marl algorithm.

Here is the complete Java class:

import oracle.pgx.api.CompiledProgram;
import oracle.pgx.api.Pgx;
import oracle.pgx.api.PgxGraph;
import oracle.pgx.api.PgxSession;
import oracle.pgx.api.internal.AnalysisResult;

public class CompilationExample {

  public static void main(String[] args) throws Exception {
    PgxSession session = Pgx.createSession("my-session");
    CompiledProgram maxDegree = session.compileProgram("examples/gm/max_degree.gm");
    PgxGraph graph = session.readGraphWithProperties("examples/graphs/connections.edge_list.json");
    AnalysisResult<Integer> result = maxDegree.run(graph);
    System.out.println("max_degree = " + result.getReturnValue() + " (took " + result.getExecutionTimeMs() + "ms)");
  }
}

To compile, run

cd $PGX_HOME
mkdir classes
javac -cp lib/embedded/*:lib/common/*:third-party/* -d classes examples/java/CompilationExample.java

To run it on your local machine, do

java -cp lib/embedded/*:lib/common/*:third-party/*:classes:conf CompilationExample

Persist a compiled algorithm into a JAR file

If you are using PGX in embedded mode, you can write a compiled algorithm into a .jar file to persist it across PGX instances by using the following APIs:

pgx> import oracle.pgx.compilers.Compilers
pgx> import oracle.pgx.compilers.GmCompilation
pgx> import oracle.pgx.compilers.Language
pgx> gmComp = Compilers.findCompiler(Language.GM)
==> oracle.pgx.compilers.gm.GmCompiler@388b401d
pgx> maxDegree = gmComp.compile("examples/gm/max_degree.gm", "max_degree")
==> oracle.pgx.compilers.gm.GmCompilationImpl@6573d2f7
pgx> maxDegree.writeAsJar(new FileOutputStream("/tmp/max-degree.jar"))
import oracle.pgx.compilers.Compilers;
import oracle.pgx.compilers.GmCompilation;
import oracle.pgx.compilers.Language;
import oracle.pgx.compilers.PgxCompiler;

...

PgxCompiler<GmCompilation> gmComp = Compilers.findCompiler(Language.GM);
GmCompilation maxDegree = gmComp.compile("examples/gm/max_degree.gm", "max_degree");
maxDegree.writeAsJar(new FileOutputStream(tmpFile));

In above example, we store the compilation artifact of the code in examples/gm/max_degree.gm into a .jar file at /tmp/max-degree.jar. We also have to provide an ID for the algorithm, so we can reference it later. In this example we use max_degree as ID.

Load a compiled algorithm

The instructions for loading a compiled algorithm depend on whether you run PGX in local mode or remote mode.

Local mode

If you run PGX in local mode (local shell mode or local Java mode) you need to add the generated .jar file to the PGX classpath. For the local shell mode you can add the .jar to the classpath by setting the CLASSPATH environment variable before starting the shell:

export CLASSPATH=/tmp/max-degree.jar
./bin/pgx

For local Java mode you need to add the algorithm .jar to the classpath when you run your user application. The instructions on how to do this depend on the way you run your Java application.

Remote mode

If you run PGX in remote mode you need to add the generated .jar file to the WEB-INF/lib directory inside the .war file. The following shell commands illustrate how this is done:

cd shared-memory/server
mkdir -p WEB-INF/lib
cp /path/to/algorithm.jar WEB-INF/lib
zip -ur pgx-webapp-19.1.0.war WEB-INF/lib

Run a compiled algorithm

You can then retrieve the compiled algorithm by looking it up via its ID:

maxDegree = session.getCompiledProgram("max_degree")