Serialization and Threads

In the next release of Jep.Net you will be able to serialize parsed expressions, the main JepInstance class, and its sub-components. This allows persistent storage and transfer between applications.

NOTE: Serialization is incomplete in Jep.Net version 1.0 and requires extensive testing. We expect to have this included and fully functional in version 1.1, which should be available within a few months. (It will be a free update for all Jep.Net v1.0 license holders).

What needs to be serialized?

Depending on your needs you may choose from three different serialization options:

Serializing an expression

The Node class itself is not serializable. Instead, a wrapper class SingularSys.Jep.Walkers.SerializableExpression is used to provide a compact serializable representation of a node. The class is constructed using new SerializedExpression(Node n) and the Node ToNode(JepInstance j) method is used to extract the node in the context of a given Jep instance.

To serialize use:

//  Set-up jep        
JepInstance j = new JepInstance();
	
// create a MemoryStream and BinaryFormatter
MemoryStream ms = new MemoryStream();
BinaryFormatter bf1 = new BinaryFormatter();  
 
// parse an expression
Node n = j.Parse("1+cos(2 th)"); 
 
// Create a SerializableExpression
SerializableExpression se = new SerializableExpression(n);
 
// Serialize the expression
bf1.Serialize(ms, o);

// extract the bytes
byte[] bytes = ms.ToArray();

To deserialize the expression use:

//  Set-up jep        
JepInstance j2 = new JepInstance();

// Create a MemoryStream and BinaryFormatter
MemoryStream ms = new MemoryStream(theByteArray);
BinaryFormatter bf1 = new BinaryFormatter();
ms.Position = 0;

// Deserialize the SerializableExpression
SerializableExpression se2 = (SerializableExpression) bf1.Deserialize(ms);

// Create a node
Node n2 = se2.ToNode(j2);

Alternatively, the serialized expression could be written to a file

....
// Set-up file stream and BinaryFormatter
Stream myStream ;
myStream = File.OpenWrite(filename);
BinaryFormatter bf1 = new BinaryFormatter();

// Serialize and Write object
bf1.Serialize(myStream, se);
myStream.Close();

....
Stream myStream = File.OpenRead(filename);
BinaryFormatter bf1 = new BinaryFormatter();
mySteam.Position = 0;

// Deserialize the SerializableExpression
SerializableExpression se2 = (SerializableExpression) bf1.Deserialize(myStream);

// Create a node
Node n2 = se2.ToNode(j2);

// Close file
myStream.Close();

Serializing the VariableTable and an expression

If you wish to serialize the values of variables for later use, then the VariableTable can be serialized. Again this methods assumes the same version and configuration of the Jep instances.

//  Set-up jep        
JepInstance j = new JepInstance();
	
// create a MemoryStream and BinaryFormatter
MemoryStream ms = new MemoryStream();
BinaryFormatter bf1 = new BinaryFormatter();  
 
// Serialize the expression
bf1.Serialize(ms, j.VarTab);

// Serialize the expression
Node n = j.Parse("1+cos(2 th)"); 
SerializableExpression se = new SerializableExpression(n);
bf1.Serialize(ms, o);

// extract the bytes
byte[] bytes = ms.ToArray();

To deserialize

// Set up JepInstance
JepInstance j2 = new JepInstance

// Create a MemoryStream and BinaryFormatter
MemoryStream ms = new MemoryStream();
BinaryFormatter bf1 = new BinaryFormatter(); 
ms.Position = 0;

// Deserialize the SerializableExpression
VariableTable vt2 = (VariableTable) bf1.Deserialize(ms);
// Set the SymbolTable as that used by the jep instance
j2.VarTab = vt2;

// Deserialize the SerializableExpression
SerializableExpression se2 = (SerializableExpression) bf1.Deserialize(ms);

// Create a node
Node n2 = se2.ToNode(j2);

Serializing the Jep instance

The Jep class and all its components are serializable, meaning that the configuration of the Jep instance can be stored. This includes the full set of variables, functions, operators, and various settings. If the ConfigurableParser is used, then its configuration is also stored. Note that changes made to the standard JavaCC parser are not recorded.

A typical setup will take 7KB with the standard parser and 12KB with the configurable parser.

//  Set-up jep        
JepInstance j = new JepInstance();
	
// create a MemoryStream and BinaryFormatter
MemoryStream ms = new MemoryStream();
BinaryFormatter bf1 = new BinaryFormatter();  
 
// Serialize the expression
bf1.Serialize(ms, j);

// Serialize the expression
Node n = j.Parse("1+cos(2 th)"); 
SerializableExpression se = new SerializableExpression(n);
bf1.Serialize(ms, o);

// extract the bytes
byte[] bytes = ms.ToArray();

To deserialize

	
// Create a MemoryStream and BinaryFormatter
MemoryStream ms = new MemoryStream();
BinaryFormatter bf1 = new BinaryFormatter(); 
ms.Position = 0;

// Deserialize the SerializableExpression
JepInstance j2 = (JepInstance) bf1.Deserialize(ms);

// Deserialize the SerializableExpression
SerializableExpression se2 = (SerializableExpression) bf1.Deserialize(ms);
Node n2 = se2.ToNode(j2);

Importing equations

The SerializedExpression class can also be used to produce copies of a node without having to serialize and deserialize.

// Create first instance
JepInstance j = new JepInstance();

// Parse equation using first instance
Node n = j.Parse("a+cos(2 th)");

// Create a SerializableExpression
SerializableExpression se = new SerializableExpression(n);

// Create second instance
JepInstance j2 = new JepInstance();

// Import expression into second instance
Node n2 = se.ToNode(j2);
top