Loading src/edu/bu/ec504/project/Molecule.java +234 −2 Original line number Diff line number Diff line Loading @@ -6,6 +6,9 @@ import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; /** * Represents a molecule containing atoms and edges. Loading Loading @@ -66,13 +69,11 @@ public class Molecule implements Serializable { // Compare the number of elements if (!Arrays.equals(this.numElements, otherMolecule.numElements)) { // System.out.println("different numElements"); return null; // Number of elements is different, molecules are not equal } // Compare the number of edges if (this.numEdges != otherMolecule.numEdges) { // System.out.println("different numEdges"); return null; // Number of edges is different, molecules are not equal } Loading Loading @@ -123,6 +124,226 @@ public class Molecule implements Serializable { return this; } /** * Finds the Most Similar Molecule */ public int mostSimilar(Molecule otherMolecule) { int similarity=0; //counts similarity points // Points for an intersection of elements between this and otherMolecule for(int i=0;i<this.numElements.length;i++) { similarity+= Math.min( this.numElements[i], otherMolecule.numElements[i]); } //Points for same number of atoms if(this.numAtoms==otherMolecule.numAtoms) { similarity++; } //Points for same number of edges if(this.numEdges==otherMolecule.numEdges) { similarity++; } // Clean the otherMolecule atom list of any marked atoms for(Atom cleanAtom : otherMolecule.atomArrayList) { cleanAtom.marked = false; //clean the connected arraylist for(int i=0;i<cleanAtom.connectedMarked.size();i++) { cleanAtom.connectedMarked.set(i,false); } } // Clean the dbMolecule atom list of any marked atoms // Compare the atom lists for(Atom dbAtom : this.atomArrayList) { boolean matchingEdge=false; for (Atom newAtom : otherMolecule.atomArrayList) { if (!newAtom.marked && newAtom.elementType == dbAtom.elementType) { //Check if elements are the same boolean [] edgeMarked = new boolean[newAtom.connected.size()]; // Compare connected of each atom //for each connected atom in dbAtom for (Atom.ElemOrderPair dbValues : dbAtom.connected.values()) { int marker=0; for (Atom.ElemOrderPair newAtomValues : newAtom.connected.values()) { //if its a match //if first 2 yes, add points for min of bondOrder between the 2 if (!newAtom.connectedMarked.get(marker) && !edgeMarked[marker] && dbValues.eType == newAtomValues.eType ) { if( dbValues.bondOrder == newAtomValues.bondOrder) { //mark the newAtom edge as already found newAtom.connectedMarked.set(marker,true); matchingEdge=true; edgeMarked[marker]=true; similarity++; //add a point for each edge that is the same break; } } marker++; } } } if(matchingEdge) { newAtom.marked=true; break; } } } // If all comparisons passed, the molecules are equal return similarity; } public Molecule isSubGraphPresent(Molecule subgraph) { //compare the number of elements for (int ii = 0; ii < numElements.length; ii++) if (this.numElements[ii] < subgraph.numElements[ii]) return null; // Compare # of edges if (this.numEdges < subgraph.numEdges) return null; //Hashmap of candidates HashMap<Atom, ArrayList<Atom>> CandidateList = new HashMap<>(); //For each atom in the array list for (Atom possibleCandidate : this.atomArrayList) { Object[] cndArray = possibleCandidate.connected.values().toArray(); for (Atom keyAtom : subgraph.atomArrayList) { if (!keyAtom.equals(possibleCandidate)) { if (keyAtom.elementType == possibleCandidate.elementType) { if (keyAtom.degree <= possibleCandidate.degree) { boolean validConnects = true; boolean[] edgeMarked = new boolean[possibleCandidate.connected.size()]; for (Atom.ElemOrderPair keyValue : keyAtom.connected.values()) { boolean edgeFound = false; for (int aa = 0; aa < edgeMarked.length; aa++) { if (!edgeMarked[aa] && keyValue.eType == ((Atom.ElemOrderPair) cndArray[aa]).eType && keyValue.bondOrder == ((Atom.ElemOrderPair) cndArray[aa]).bondOrder) { edgeMarked[aa] = true; edgeFound = true; break; } } if (!edgeFound) { validConnects = false; } } if (validConnects) { //add atom to list if (!CandidateList.containsKey(keyAtom)) { CandidateList.put(keyAtom, new ArrayList<>()); } CandidateList.get(keyAtom).add(possibleCandidate); } } } } } } //if it matches the type (elem and connections) as one in the subgraph, add it to candidate list for subgrpah //Look through list of candidates, and if any of the lists are empty return null for (Atom sweep : subgraph.atomArrayList) if (!CandidateList.containsKey(sweep)) return null; //Unmark all atoms (marked = visited) for (Atom cleanAtom : this.atomArrayList) cleanAtom.marked = false; for (Atom cleanAtom : subgraph.atomArrayList) cleanAtom.marked = false; //BFS node: parent atom, other candidates //Make a linked list of the BFS node LinkedList<subGraphNode> subgraphTraversal = new LinkedList<subGraphNode>(); //head is the first atom (parent is null) subgraphTraversal.addFirst(new subGraphNode(null, subgraph.atomArrayList.get(0))); for (Atom c : CandidateList.get(subgraph.atomArrayList.get(0))) { //c.marked = true; subgraphTraversal.get(0).options.add(c); } subgraphTraversal.getFirst().self.marked = true; int pointer = 0; while(true) { subGraphNode current = subgraphTraversal.get(pointer); if(current.options.isEmpty()) { //If there are no options to choose from, move pointer backwards (to parent) and restart cycke //if parent is null return null if(current.parent == null) return null; else pointer = subgraphTraversal.indexOf(current.parent); } else { boolean mustReverse = false; int adjAdded = 0; //remove option (choose it) Atom path = current.options.remove(0); path.marked = true; //else add adjacent local nodes for(String k :current.self.connected.keySet()) { for(Atom a: subgraph.atomArrayList) { if(!a.marked && a.getName().equals(k)) { a.marked = true; subgraphTraversal.add(new subGraphNode(current,a)); adjAdded++; //add options to adjacent (checking validity:not marked and connected to parent) ArrayList<Atom> aList = CandidateList.get(a); boolean candFound = false; for(Atom cand: aList) { if(!cand.marked) { //not marked if(cand.connected.containsKey(path.getName())) { //is connected subgraphTraversal.getLast().options.add(cand); candFound = true; } } } if(!candFound) mustReverse = true; break; } } } if(mustReverse) { path.marked = false; for(int ff = 0; ff < adjAdded;ff++) { subgraphTraversal.getLast().self.marked = false; subgraphTraversal.remove(subgraphTraversal.getLast()); } } else{ if(subgraphTraversal.getLast().equals(subgraphTraversal.get(pointer))) return this; pointer++; } } } } /** * Return number of atoms of the molecule */ Loading @@ -130,6 +351,17 @@ public class Molecule implements Serializable { return numAtoms; } class subGraphNode implements Serializable { public subGraphNode parent; public ArrayList<Atom> options; public Atom self; public subGraphNode(subGraphNode p, Atom s) { this.parent = p; this.self = s; this.options = new ArrayList<Atom>(); } }; } Loading
src/edu/bu/ec504/project/Molecule.java +234 −2 Original line number Diff line number Diff line Loading @@ -6,6 +6,9 @@ import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; /** * Represents a molecule containing atoms and edges. Loading Loading @@ -66,13 +69,11 @@ public class Molecule implements Serializable { // Compare the number of elements if (!Arrays.equals(this.numElements, otherMolecule.numElements)) { // System.out.println("different numElements"); return null; // Number of elements is different, molecules are not equal } // Compare the number of edges if (this.numEdges != otherMolecule.numEdges) { // System.out.println("different numEdges"); return null; // Number of edges is different, molecules are not equal } Loading Loading @@ -123,6 +124,226 @@ public class Molecule implements Serializable { return this; } /** * Finds the Most Similar Molecule */ public int mostSimilar(Molecule otherMolecule) { int similarity=0; //counts similarity points // Points for an intersection of elements between this and otherMolecule for(int i=0;i<this.numElements.length;i++) { similarity+= Math.min( this.numElements[i], otherMolecule.numElements[i]); } //Points for same number of atoms if(this.numAtoms==otherMolecule.numAtoms) { similarity++; } //Points for same number of edges if(this.numEdges==otherMolecule.numEdges) { similarity++; } // Clean the otherMolecule atom list of any marked atoms for(Atom cleanAtom : otherMolecule.atomArrayList) { cleanAtom.marked = false; //clean the connected arraylist for(int i=0;i<cleanAtom.connectedMarked.size();i++) { cleanAtom.connectedMarked.set(i,false); } } // Clean the dbMolecule atom list of any marked atoms // Compare the atom lists for(Atom dbAtom : this.atomArrayList) { boolean matchingEdge=false; for (Atom newAtom : otherMolecule.atomArrayList) { if (!newAtom.marked && newAtom.elementType == dbAtom.elementType) { //Check if elements are the same boolean [] edgeMarked = new boolean[newAtom.connected.size()]; // Compare connected of each atom //for each connected atom in dbAtom for (Atom.ElemOrderPair dbValues : dbAtom.connected.values()) { int marker=0; for (Atom.ElemOrderPair newAtomValues : newAtom.connected.values()) { //if its a match //if first 2 yes, add points for min of bondOrder between the 2 if (!newAtom.connectedMarked.get(marker) && !edgeMarked[marker] && dbValues.eType == newAtomValues.eType ) { if( dbValues.bondOrder == newAtomValues.bondOrder) { //mark the newAtom edge as already found newAtom.connectedMarked.set(marker,true); matchingEdge=true; edgeMarked[marker]=true; similarity++; //add a point for each edge that is the same break; } } marker++; } } } if(matchingEdge) { newAtom.marked=true; break; } } } // If all comparisons passed, the molecules are equal return similarity; } public Molecule isSubGraphPresent(Molecule subgraph) { //compare the number of elements for (int ii = 0; ii < numElements.length; ii++) if (this.numElements[ii] < subgraph.numElements[ii]) return null; // Compare # of edges if (this.numEdges < subgraph.numEdges) return null; //Hashmap of candidates HashMap<Atom, ArrayList<Atom>> CandidateList = new HashMap<>(); //For each atom in the array list for (Atom possibleCandidate : this.atomArrayList) { Object[] cndArray = possibleCandidate.connected.values().toArray(); for (Atom keyAtom : subgraph.atomArrayList) { if (!keyAtom.equals(possibleCandidate)) { if (keyAtom.elementType == possibleCandidate.elementType) { if (keyAtom.degree <= possibleCandidate.degree) { boolean validConnects = true; boolean[] edgeMarked = new boolean[possibleCandidate.connected.size()]; for (Atom.ElemOrderPair keyValue : keyAtom.connected.values()) { boolean edgeFound = false; for (int aa = 0; aa < edgeMarked.length; aa++) { if (!edgeMarked[aa] && keyValue.eType == ((Atom.ElemOrderPair) cndArray[aa]).eType && keyValue.bondOrder == ((Atom.ElemOrderPair) cndArray[aa]).bondOrder) { edgeMarked[aa] = true; edgeFound = true; break; } } if (!edgeFound) { validConnects = false; } } if (validConnects) { //add atom to list if (!CandidateList.containsKey(keyAtom)) { CandidateList.put(keyAtom, new ArrayList<>()); } CandidateList.get(keyAtom).add(possibleCandidate); } } } } } } //if it matches the type (elem and connections) as one in the subgraph, add it to candidate list for subgrpah //Look through list of candidates, and if any of the lists are empty return null for (Atom sweep : subgraph.atomArrayList) if (!CandidateList.containsKey(sweep)) return null; //Unmark all atoms (marked = visited) for (Atom cleanAtom : this.atomArrayList) cleanAtom.marked = false; for (Atom cleanAtom : subgraph.atomArrayList) cleanAtom.marked = false; //BFS node: parent atom, other candidates //Make a linked list of the BFS node LinkedList<subGraphNode> subgraphTraversal = new LinkedList<subGraphNode>(); //head is the first atom (parent is null) subgraphTraversal.addFirst(new subGraphNode(null, subgraph.atomArrayList.get(0))); for (Atom c : CandidateList.get(subgraph.atomArrayList.get(0))) { //c.marked = true; subgraphTraversal.get(0).options.add(c); } subgraphTraversal.getFirst().self.marked = true; int pointer = 0; while(true) { subGraphNode current = subgraphTraversal.get(pointer); if(current.options.isEmpty()) { //If there are no options to choose from, move pointer backwards (to parent) and restart cycke //if parent is null return null if(current.parent == null) return null; else pointer = subgraphTraversal.indexOf(current.parent); } else { boolean mustReverse = false; int adjAdded = 0; //remove option (choose it) Atom path = current.options.remove(0); path.marked = true; //else add adjacent local nodes for(String k :current.self.connected.keySet()) { for(Atom a: subgraph.atomArrayList) { if(!a.marked && a.getName().equals(k)) { a.marked = true; subgraphTraversal.add(new subGraphNode(current,a)); adjAdded++; //add options to adjacent (checking validity:not marked and connected to parent) ArrayList<Atom> aList = CandidateList.get(a); boolean candFound = false; for(Atom cand: aList) { if(!cand.marked) { //not marked if(cand.connected.containsKey(path.getName())) { //is connected subgraphTraversal.getLast().options.add(cand); candFound = true; } } } if(!candFound) mustReverse = true; break; } } } if(mustReverse) { path.marked = false; for(int ff = 0; ff < adjAdded;ff++) { subgraphTraversal.getLast().self.marked = false; subgraphTraversal.remove(subgraphTraversal.getLast()); } } else{ if(subgraphTraversal.getLast().equals(subgraphTraversal.get(pointer))) return this; pointer++; } } } } /** * Return number of atoms of the molecule */ Loading @@ -130,6 +351,17 @@ public class Molecule implements Serializable { return numAtoms; } class subGraphNode implements Serializable { public subGraphNode parent; public ArrayList<Atom> options; public Atom self; public subGraphNode(subGraphNode p, Atom s) { this.parent = p; this.self = s; this.options = new ArrayList<Atom>(); } }; }