com.actelion.research.chem.mcs.ExhaustiveFragmentGeneratorBonds Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
package com.actelion.research.chem.mcs;
import java.util.Date;
import java.util.List;
import com.actelion.research.chem.ExtendedMolecule;
import com.actelion.research.chem.properties.complexity.ContainerFragBondsSolutions;
import com.actelion.research.chem.properties.complexity.IBitArray;
import com.actelion.research.util.Formatter;
import com.actelion.research.util.SizeOf;
import com.actelion.research.util.datamodel.IntArray;
/*
* Copyright (c) 1997 - 2016
* Actelion Pharmaceuticals Ltd.
* Gewerbestrasse 16
* CH-4123 Allschwil, Switzerland
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
public class ExhaustiveFragmentGeneratorBonds {
private static boolean ELUSIVE = false;
public static final long LIMIT_NEIGHBOURS_SINCE_LAST_ADDED = 100 * 1000 * 1000;
// This list contains the solutions. Each row in the list contains the solutions for the corresponding number of atom types.
// Consequently, the first two rows are empty.
private ContainerFragBondsSolutions containerDataFragDefByBonds;
private ExtendedMolecule mol;
private int nBondsMolecule;
private int maximumNumberBondsInFrag;
private IntArray arrIndexReachableNeighbours;
private boolean fragmentsGenerated;
private boolean capacityLimitBreakes;
private long solutionAdded;
private int totalMaximumCapacity;
/**
* @param bits maximum fragment size that can be stored as number of bonds.
*/
public ExhaustiveFragmentGeneratorBonds(int bits, int totalMaximumCapacity) {
ContainerFragBondsSolutions.ELUSIVE = ELUSIVE;
this.totalMaximumCapacity = totalMaximumCapacity;
containerDataFragDefByBonds = new ContainerFragBondsSolutions(bits, totalMaximumCapacity);
arrIndexReachableNeighbours = new IntArray();
if(ELUSIVE)
System.out.println("ExhaustiveFragmentGeneratorBonds constructor finished, used mem " + SizeOf.usedMemoryMB() + "[MB].");
}
public void set(ExtendedMolecule mol, int nMaximumNumberBonds) {
this.mol = mol;
nBondsMolecule = mol.getBonds();
if(nBondsMolecule > containerDataFragDefByBonds.getSizeBinaryArray()){
throw new RuntimeException("Maximum number of bonds exceeded.");
}
this.maximumNumberBondsInFrag = Math.min(nMaximumNumberBonds, containerDataFragDefByBonds.getMaximumCapacityBondsInFragment());
fragmentsGenerated = false;
capacityLimitBreakes=false;
containerDataFragDefByBonds.setBondsMolecule(nBondsMolecule);
}
private void initDataContainerAllSingleBonds(){
containerDataFragDefByBonds.reset();
for (int i = 0; i < nBondsMolecule; i++) {
IBitArray f = containerDataFragDefByBonds.get();
f.setBit(i);
containerDataFragDefByBonds.addFacultative(f);
}
}
private void initDataContainerOneSingleBond(int indexBond) {
containerDataFragDefByBonds.reset();
IBitArray f = containerDataFragDefByBonds.get();
f.setBit(indexBond);
containerDataFragDefByBonds.addFacultative(f);
}
public void generateFragmentsAllBonds(){
initDataContainerAllSingleBonds();
generateFragments();
}
public void generateFragmentsForSingleBond(int indexBond) {
initDataContainerOneSingleBond(indexBond);
generateFragments();
}
private void generateFragments(){
int maxNumBondsFrag = Math.min(nBondsMolecule, maximumNumberBondsInFrag);
if(maxNumBondsFrag==1){
return;
}
long neighboursTotal = 0;
long addedTotal = 0;
if(ELUSIVE) {
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() start record capacity " + Formatter.group(containerDataFragDefByBonds.getAvailable()) + ".");
}
maximumCapacityBreak:
for (int i = 1; i < maxNumBondsFrag; i++) {
List liParent = containerDataFragDefByBonds.getList(i);
if(ELUSIVE) {
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() bonds " + i + ". Parents " + Formatter.group(liParent.size()) + ".");
}
long added = 0;
long neighbours = 0;
long neighboursSinceLastAdded = 0;
for (IBitArray fParent : liParent) {
IntArray arrBondsReachable = getAllReachableNeighbourBonds(mol, fParent);
for (int j = 0; j < arrBondsReachable.length(); j++) {
IBitArray fChildAddedBond = containerDataFragDefByBonds.getWithCopy(fParent);
fChildAddedBond.setBit(arrBondsReachable.get(j));
// System.out.println(fChildAddedBond.toString());
if(containerDataFragDefByBonds.addFacultative(fChildAddedBond)){
added++;
addedTotal++;
neighboursSinceLastAdded = 0;
if(addedTotal>totalMaximumCapacity) {
if(ELUSIVE) {
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() maximum capacity (" + totalMaximumCapacity + ") break.");
log(neighbours, neighboursTotal, added, addedTotal, neighboursSinceLastAdded);
}
// Clear all records for this number of bonds.
containerDataFragDefByBonds.reset(fChildAddedBond.getBitsSet());
break maximumCapacityBreak;
}
}
neighbours++;
neighboursSinceLastAdded++;
if(neighbours % 50000000 == 0){
if(ELUSIVE) {
log(neighbours, neighboursTotal, added, addedTotal, neighboursSinceLastAdded);
}
}
}
// if(neighboursSinceLastAdded > LIMIT_NEIGHBOURS_SINCE_LAST_ADDED) {
if(neighboursSinceLastAdded > totalMaximumCapacity) {
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments(). Break for fragments with " + i + " bonds. Generated " + totalMaximumCapacity + " neighbours since last add to hash map.");
break;
}
}
// System.out.println("Bonds\t" + i + "\tparents\t" + liParent.size() + "\tneighbours added\t" + added);
neighboursTotal += neighbours;
if(ELUSIVE) {
log(neighbours, neighboursTotal, added, addedTotal, neighboursSinceLastAdded);
}
}
fragmentsGenerated = true;
if(ELUSIVE) {
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() getTotalSizeResultList() " + Formatter.group(containerDataFragDefByBonds.getTotalSizeResults()) + ".");
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() solutionAdded " + Formatter.group(solutionAdded) + ".");
}
}
private void log(long neighbours, long neighboursTotal, long added, long addedTotal, long neighboursSinceLastAdded){
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() " + new Date().toString() + ".");
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() neighbours generated " + Formatter.group(neighbours) + ".");
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() neighbours generated total " + Formatter.group(neighboursTotal) + ".");
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() solutions added " + Formatter.group(added) + ".");
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() solutions added total " + Formatter.group(addedTotal) + ".");
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() available " + Formatter.group(containerDataFragDefByBonds.getAvailable()) + ".");
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() capacity " + Formatter.group(containerDataFragDefByBonds.getCapacity()) + ".");
System.out.println("ExhaustiveFragmentGeneratorBonds generateFragments() neighboursSinceLastAdded " + Formatter.group(neighboursSinceLastAdded) + ".");
}
/**
* Returns list with indices for fragments with size
bonds. The indices are coded as bit lists.
* @param bonds
* @return
*/
public List getFragments(int bonds) {
if(!fragmentsGenerated){
throw new RuntimeException("Fragments have to be generated first. Call generateFragments().");
}
return containerDataFragDefByBonds.getList(bonds);
}
/**
* get all bonds that can be reached in one step from the input bonds.
* @param mol
* @param livIndexBond
* @return
*/
private final IntArray getAllReachableNeighbourBonds(ExtendedMolecule mol, IBitArray livIndexBond){
arrIndexReachableNeighbours.reset();
for (int i = 0; i < nBondsMolecule; i++) {
if(!livIndexBond.isBitSet(i)){
continue;
}
final int indexBond = i;
final int indexAtom1 = mol.getBondAtom(0, indexBond);
final int indexAtom2 = mol.getBondAtom(1, indexBond);
final int nConnected1 = mol.getAllConnAtoms(indexAtom1);
for (int j = 0; j < nConnected1; j++) {
int indexAtConn = mol.getConnAtom(indexAtom1, j);
int indexBondConnected = mol.getBond(indexAtom1, indexAtConn);
if(!livIndexBond.isBitSet(indexBondConnected)) {
solutionAdded++;
arrIndexReachableNeighbours.add(indexBondConnected);
}
}
final int nConnected2 = mol.getAllConnAtoms(indexAtom2);
for (int j = 0; j < nConnected2; j++) {
int indexAtConn = mol.getConnAtom(indexAtom2, j);
int indexBondConnected = mol.getBond(indexAtom2, indexAtConn);
if(!livIndexBond.isBitSet(indexBondConnected)) {
solutionAdded++;
arrIndexReachableNeighbours.add(indexBondConnected);
}
}
}
return arrIndexReachableNeighbours;
}
/**
* If true not all index combinations were generated.
* Starts with 0 for each new molecule.
* @return
*/
public boolean isCapacityLimitBreakes() {
return capacityLimitBreakes;
}
public int getSizeArrayLIV(){
int maxSizeIntVec = (containerDataFragDefByBonds.getSizeBinaryArray() + Integer.SIZE-1)/ Integer.SIZE;
return maxSizeIntVec;
}
public int getMaximumCapacityBondsInFragment() {
return containerDataFragDefByBonds.getMaximumCapacityBondsInFragment();
}
public int getMaximumNumberBondsInMolecule(){
return containerDataFragDefByBonds.getMaximumNumberBondsInMolecule();
}
/**
* @return the eLUSIVE
*/
public static boolean isELUSIVE() {
return ELUSIVE;
}
/**
* @param elusive the ELUSIVE to set
*/
public static void setELUSIVE(boolean elusive) {
ELUSIVE = elusive;
ContainerFragBondsSolutions.ELUSIVE = ELUSIVE;
}
}