refactor to construct the bipartite graph directly, rather than by using an adjacency matrix and a graph generator.

This commit is contained in:
eugenefischer
2025-04-10 11:47:15 -05:00
parent bcf5a4c749
commit e1888a99c6
2 changed files with 83 additions and 44 deletions

View File

@@ -241,7 +241,7 @@ public class Plate {
sequencesAndMisreads.put(currentSequence, new ArrayList<>());
}
//The specific misread hasn't happened before
if (rand.nextDouble() >= errorCollisionRate || sequencesAndMisreads.get(currentSequence).size() == 0) {
if (rand.nextDouble() >= errorCollisionRate || sequencesAndMisreads.get(currentSequence).isEmpty()) {
//The misread doesn't collide with a real sequence already on the plate and some sequences have already been read
if(rand.nextDouble() >= realSequenceCollisionRate || !sequenceMap.isEmpty()){
StringBuilder spurious = new StringBuilder(currentSequence);

View File

@@ -70,58 +70,97 @@ public class Simulator implements GraphModificationFunctions {
if(verbose){System.out.println("Total beta sequence wells removed: " + betaWellsRemoved);}
}
//construct the graph. For simplicity, going to make
if(verbose){System.out.println("Making vertex maps");}
//For the SimpleWeightedBipartiteGraphMatrixGenerator, all vertices must have
//distinct numbers associated with them. Since I'm using a 2D array, that means
//distinct indices between the rows and columns. vertexStartValue lets me track where I switch
//from numbering rows to columns, so I can assign unique numbers to every vertex, and then
//subtract the vertexStartValue from betas to use their vertex labels as array indices
int vertexStartValue = 0;
//keys are sequential integer vertices, values are alphas
Map<String, Integer> plateAtoVMap = makeSequenceToVertexMap(alphaSequences, vertexStartValue);
//new start value for vertex to beta map should be one more than final vertex value in alpha map
vertexStartValue += plateAtoVMap.size();
//keys are betas, values are sequential integers
Map<String, Integer> plateBtoVMap = makeSequenceToVertexMap(betaSequences, vertexStartValue);
if(verbose){System.out.println("Vertex maps made");}
//make adjacency matrix for bipartite graph generator
//(technically this is only 1/4 of an adjacency matrix, but that's all you need
//for a bipartite graph, and all the SimpleWeightedBipartiteGraphMatrixGenerator class expects.)
if(verbose){System.out.println("Making adjacency matrix");}
double[][] weights = new double[plateAtoVMap.size()][plateBtoVMap.size()];
fillAdjacencyMatrix(weights, vertexStartValue, alphaSequences, betaSequences, plateAtoVMap, plateBtoVMap);
if(verbose){System.out.println("Adjacency matrix made");}
/*
* The commented out code below works beautifully for small enough graphs. However, after implementing a
* Zipf distribution and attempting to simulate Experiment 3 from the paper again, I discovered that
* this method uses too much memory. Even a 120GB heap is not enough to build this adjacency matrix.
* So I'm going to attempt to build this graph directly and see if that is less memory intensive
*/
// //construct the graph. For simplicity, going to make
// if(verbose){System.out.println("Making vertex maps");}
// //For the SimpleWeightedBipartiteGraphMatrixGenerator, all vertices must have
// //distinct numbers associated with them. Since I'm using a 2D array, that means
// //distinct indices between the rows and columns. vertexStartValue lets me track where I switch
// //from numbering rows to columns, so I can assign unique numbers to every vertex, and then
// //subtract the vertexStartValue from betas to use their vertex labels as array indices
// int vertexStartValue = 0;
// //keys are sequential integer vertices, values are alphas
// Map<String, Integer> plateAtoVMap = makeSequenceToVertexMap(alphaSequences, vertexStartValue);
// //new start value for vertex to beta map should be one more than final vertex value in alpha map
// vertexStartValue += plateAtoVMap.size();
// //keys are betas, values are sequential integers
// Map<String, Integer> plateBtoVMap = makeSequenceToVertexMap(betaSequences, vertexStartValue);
// if(verbose){System.out.println("Vertex maps made");}
// //make adjacency matrix for bipartite graph generator
// //(technically this is only 1/4 of an adjacency matrix, but that's all you need
// //for a bipartite graph, and all the SimpleWeightedBipartiteGraphMatrixGenerator class expects.)
// if(verbose){System.out.println("Making adjacency matrix");}
// double[][] weights = new double[plateAtoVMap.size()][plateBtoVMap.size()];
// fillAdjacencyMatrix(weights, vertexStartValue, alphaSequences, betaSequences, plateAtoVMap, plateBtoVMap);
// if(verbose){System.out.println("Adjacency matrix made");}
// //make bipartite graph
// if(verbose){System.out.println("Making bipartite weighted graph");}
// //the graph object
// SimpleWeightedGraph<Vertex, DefaultWeightedEdge> graph =
// new SimpleWeightedGraph<>(DefaultWeightedEdge.class);
// //the graph generator
// SimpleWeightedBipartiteGraphMatrixGenerator graphGenerator = new SimpleWeightedBipartiteGraphMatrixGenerator();
// //the list of alpha vertices
// List<Vertex> alphaVertices = new ArrayList<>();
// for (String seq : plateAtoVMap.keySet()) {
// Vertex alphaVertex = new Vertex(alphaSequences.get(seq), plateAtoVMap.get(seq));
// alphaVertices.add(alphaVertex);
// }
// //Sort to make sure the order of vertices in list matches the order of the adjacency matrix
// Collections.sort(alphaVertices);
// //Add ordered list of vertices to the graph
// graphGenerator.first(alphaVertices);
// //the list of beta vertices
// List<Vertex> betaVertices = new ArrayList<>();
// for (String seq : plateBtoVMap.keySet()) {
// Vertex betaVertex = new Vertex(betaSequences.get(seq), plateBtoVMap.get(seq));
// betaVertices.add(betaVertex);
// }
// //Sort to make sure the order of vertices in list matches the order of the adjacency matrix
// Collections.sort(betaVertices);
// //Add ordered list of vertices to the graph
// graphGenerator.second(betaVertices);
// //use adjacency matrix of weight created previously
// graphGenerator.weights(weights);
// graphGenerator.generateGraph(graph);
//make bipartite graph
if(verbose){System.out.println("Making bipartite weighted graph");}
//the graph object
SimpleWeightedGraph<Vertex, DefaultWeightedEdge> graph =
new SimpleWeightedGraph<>(DefaultWeightedEdge.class);
//the graph generator
SimpleWeightedBipartiteGraphMatrixGenerator graphGenerator = new SimpleWeightedBipartiteGraphMatrixGenerator();
//the list of alpha vertices
int vertexLabelValue = 0;
//create and add alpha sequence vertices
List<Vertex> alphaVertices = new ArrayList<>();
for (String seq : plateAtoVMap.keySet()) {
Vertex alphaVertex = new Vertex(alphaSequences.get(seq), plateAtoVMap.get(seq));
alphaVertices.add(alphaVertex);
for (Map.Entry<String, SequenceRecord> entry: alphaSequences.entrySet()) {
alphaVertices.add(new Vertex(entry.getValue(), vertexLabelValue));
vertexLabelValue++;
}
//Sort to make sure the order of vertices in list matches the order of the adjacency matrix
Collections.sort(alphaVertices);
//Add ordered list of vertices to the graph
graphGenerator.first(alphaVertices);
//the list of beta vertices
alphaVertices.forEach(graph::addVertex);
//add beta sequence vertices
List<Vertex> betaVertices = new ArrayList<>();
for (String seq : plateBtoVMap.keySet()) {
Vertex betaVertex = new Vertex(betaSequences.get(seq), plateBtoVMap.get(seq));
betaVertices.add(betaVertex);
for (Map.Entry<String, SequenceRecord> entry: betaSequences.entrySet()) {
betaVertices.add(new Vertex(entry.getValue(), vertexLabelValue));
vertexLabelValue++;
}
//Sort to make sure the order of vertices in list matches the order of the adjacency matrix
Collections.sort(betaVertices);
//Add ordered list of vertices to the graph
graphGenerator.second(betaVertices);
//use adjacency matrix of weight created previously
graphGenerator.weights(weights);
graphGenerator.generateGraph(graph);
betaVertices.forEach(graph::addVertex);
//add edges
for(Vertex alpha: alphaVertices){
for(Vertex beta: betaVertices) {
Set<Integer> sharedWells = alpha.getRecord().getWells();
sharedWells.retainAll(beta.getRecord().getWells());
if(!sharedWells.isEmpty()) {
DefaultWeightedEdge edge = graph.addEdge(alpha, beta);
graph.setEdgeWeight(edge, sharedWells.size());
}
}
}
if(verbose){System.out.println("Graph created");}
//stop timing
Instant stop = Instant.now();