## What is a sequence?

A sequence is a group of vertices that is repeated multiple times in the network. The vertices in one group can (optionally) depend on vertices in the previous group. They typically represent a concept larger than a vertex like an agent in an ABM, a time series or some observations that are associated.

# Examples

Here are some examples that will walk you through the process of developing with Sequences.

## Writing time series

This example shows you how you can write a simple time series model using Sequences

```
DoubleVertex two = new ConstantDoubleVertex(2);
// Define the labels of vertices we will use in our Sequence
VertexLabel x1Label = new VertexLabel("x1");
VertexLabel x2Label = new VertexLabel("x2");
// Define a factory method that creates proxy vertices using the proxy vertex labels and then uses these
// to define the computation graph of the Sequence.
// Note we have labeled the output vertices of this SequenceItem
Consumer<SequenceItem> factory = sequenceItem -> {
// Define the Proxy Vertices which stand in for a Vertex from the previous SequenceItem.
// They will be automatically wired up when you construct the Sequence.
// i.e. these are the 'inputs' to our SequenceItem
DoubleProxyVertex x1Input = sequenceItem.addDoubleProxyFor(x1Label);
DoubleProxyVertex x2Input = sequenceItem.addDoubleProxyFor(x2Label);
DoubleVertex x1Output = x1Input.multiply(two).setLabel(x1Label);
DoubleVertex x2Output = x2Input.plus(x1Output).setLabel(x2Label);
sequenceItem.addAll(x1Output, x2Output);
};
// Create the starting values of our sequence
DoubleVertex x1Start = new ConstantDoubleVertex(4).setLabel(x1Label);
DoubleVertex x2Start = new ConstantDoubleVertex(4).setLabel(x2Label);
VertexDictionary dictionary = SimpleVertexDictionary.of(x1Start, x2Start);
Sequence sequence = new SequenceBuilder<Integer>()
.withInitialState(dictionary)
.named("Keanu-Example")
.count(5)
.withFactory(factory)
.build();
// We can now put all the vertices in the sequence into a Bayes Net:
BayesianNetwork network = sequence.toBayesianNetwork();
// Within `network` our vertices will have the labels of the form:
// Keanu-Example.Sequence_Item_<<index>>.<<hash>>.<<vertex-label>>
// where the <<hash>> is a unique identifier for the Sequence.
// You can get all the vertices with a particular name, regardless of which SequenceItem they belong to.
List<Vertex> allXVertices = network.getVerticesIgnoringNamespace(x1Label.getUnqualifiedName());
// You get vertices from specific sequence items
// For instance here we retrieve a vertex from the last sequence item
Vertex x1Retrieved = sequence.getLastItem().get(x1Label);
// Or you can iterate over all the sequence items using an iterator
for (SequenceItem item : sequence) {
Vertex x2Retrieved = item.get(x2Label);
}
// Or you can get the SequenceItem as a list to retrieve an item at a specific index
List<SequenceItem> sequenceItems = sequence.asList();
SequenceItem secondSequenceItem = sequenceItems.get(1);
Vertex x2InSecondSequenceItem = secondSequenceItem.get(x2Label);
// Finally, you may want to save your sequence to disk and then load it back later.
// Firstly you can use the standard ProtobufSaver to save `network` to disk.
ProtobufSaver saver = new ProtobufSaver(network);
saver.save(new FileOutputStream(new File("file_name.proto")), false);
// Now you can actually use Keanu to reconstruct the Sequence object
ProtobufLoader loader = new ProtobufLoader();
BayesianNetwork reconstructedNetwork = loader.loadNetwork(new FileInputStream(new File("file_name.proto")));
Sequence reconstructedSequence = SequenceLoader.loadFromBayesNet(reconstructedNetwork);
x1Retrieved = reconstructedSequence.asList().get(0).get(x1Label);
```

Note: by using the `.withFactories`

method on the builder, rather than the `.withFactory`

, it is possible
to have factories which use proxy input vertices which are defined in other factories.
i.e. your vertices can cross factories.

## Observing many associated data points

This example shows you how you can repeat logic over many observed data points which are associated by having a dependency on a common global value. Here they are the intercept and weights of a linear regression model.

Letâ€™s say you have a class `MyData`

that looks like this:

```
public static class MyData {
public double x;
public double y;
public MyData(String x, String y) {
this.x = Double.parseDouble(x);
this.y = Double.parseDouble(y);
}
}
```

This is an example of how you could pull in data from a csv file and run linear regression, using a sequence to build identical sections of the graph for each line of the csv.

```
/**
* Each sequence item contains a linear regression model:
* VertexY = VertexX * VertexM + VertexB
*
* @param dataFileName The input data file defines, for each sequence item:
* - the value of the input, VertexX
* - the value of the observed output, VertexY
*/
public Sequence buildSequence(String dataFileName) {
//Parse the csv data to MyData objects
List<MyData> allMyData = ReadCsv.fromFile(dataFileName)
.asRowsDefinedBy(MyData.class)
.load();
DoubleVertex m = new GaussianVertex(0, 1);
DoubleVertex b = new GaussianVertex(0, 1);
VertexLabel xLabel = new VertexLabel("x");
VertexLabel yLabel = new VertexLabel("y");
//Build sequence from each line in the csv
Sequence sequence = new SequenceBuilder<MyData>()
.fromIterator(allMyData.iterator())
.withFactory((item, csvMyData) -> {
DoubleVertex x = new ConstantDoubleVertex(csvMyData.x).setLabel(xLabel);
DoubleVertex y = m.multiply(x).plus(b).setLabel(yLabel);
DoubleVertex yObserved = new GaussianVertex(y, 1);
yObserved.observe(csvMyData.y);
// this labels the x and y vertex for later use
item.add(x);
item.add(y);
})
.build();
//now you have access to the "x" from any one of the sequence
DoubleTensor valueForXAtCSVLine1 = sequence.asList()
.get(1) // get sequence item 1 which is built from csv line 1
.<DoubleVertex>get(xLabel) //get the vertex that we labelled "x" in that item
.getValue(); //get the value from that vertex
//Now run an inference algorithm on vertex m and vertex b and you have linear regression
return sequence;
}
```