chemruby 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +120 -0
 - data/Rakefile +195 -0
 - data/ext/extconf.rb +4 -0
 - data/ext/subcomp.c +416 -0
 - data/lib/chem.rb +130 -0
 - data/lib/chem/appl.rb +1 -0
 - data/lib/chem/appl/chem3dole.rb +36 -0
 - data/lib/chem/appl/tinker/nucleic.rb +40 -0
 - data/lib/chem/appl/tinker/tinker_reader.rb +43 -0
 - data/lib/chem/data.rb +4 -0
 - data/lib/chem/data/atomic_weight.rb +124 -0
 - data/lib/chem/data/character.rb +2 -0
 - data/lib/chem/data/electronegativity.rb +14 -0
 - data/lib/chem/data/periodic_table.rb +6 -0
 - data/lib/chem/data/prime_numbers.rb +1 -0
 - data/lib/chem/data/vdw_radii.rb +1 -0
 - data/lib/chem/db.rb +64 -0
 - data/lib/chem/db/cansmi.rb +234 -0
 - data/lib/chem/db/cdx.rb +1525 -0
 - data/lib/chem/db/eps.rb +164 -0
 - data/lib/chem/db/g98.rb +909 -0
 - data/lib/chem/db/gspan.rb +130 -0
 - data/lib/chem/db/iupac.rb +5 -0
 - data/lib/chem/db/iupac/a_1.rb +46 -0
 - data/lib/chem/db/iupac/iuparser.rb +226 -0
 - data/lib/chem/db/iupac/iuparser.ry +97 -0
 - data/lib/chem/db/iupac/postfix.rb +2 -0
 - data/lib/chem/db/kcf.rb +390 -0
 - data/lib/chem/db/kcf_glycan.rb +19 -0
 - data/lib/chem/db/kegg.rb +516 -0
 - data/lib/chem/db/linucs/linparser.rb +144 -0
 - data/lib/chem/db/linucs/linucs.ry +53 -0
 - data/lib/chem/db/mdl.rb +379 -0
 - data/lib/chem/db/molconnz.rb +12 -0
 - data/lib/chem/db/mopac.rb +88 -0
 - data/lib/chem/db/msi.rb +107 -0
 - data/lib/chem/db/pdb_dic.rb +115 -0
 - data/lib/chem/db/pdf.rb +131 -0
 - data/lib/chem/db/pubchem.rb +113 -0
 - data/lib/chem/db/rmagick.rb +70 -0
 - data/lib/chem/db/sdf.rb +37 -0
 - data/lib/chem/db/smbl.rb +88 -0
 - data/lib/chem/db/smiles.rb +2 -0
 - data/lib/chem/db/smiles/smiles.ry +203 -0
 - data/lib/chem/db/smiles/smiparser.rb +375 -0
 - data/lib/chem/db/swf.rb +74 -0
 - data/lib/chem/db/sybyl.rb +150 -0
 - data/lib/chem/db/tinker.rb +77 -0
 - data/lib/chem/db/types/type_cansmi.rb +9 -0
 - data/lib/chem/db/types/type_cdx.rb +24 -0
 - data/lib/chem/db/types/type_gspan.rb +31 -0
 - data/lib/chem/db/types/type_kcf.rb +28 -0
 - data/lib/chem/db/types/type_kcf_glycan.rb +26 -0
 - data/lib/chem/db/types/type_kegg.rb +92 -0
 - data/lib/chem/db/types/type_mdl.rb +31 -0
 - data/lib/chem/db/types/type_pdf.rb +33 -0
 - data/lib/chem/db/types/type_png.rb +31 -0
 - data/lib/chem/db/types/type_rxn.rb +25 -0
 - data/lib/chem/db/types/type_sdf.rb +25 -0
 - data/lib/chem/db/types/type_sybyl.rb +30 -0
 - data/lib/chem/db/types/type_xyz.rb +26 -0
 - data/lib/chem/db/vector.rb +128 -0
 - data/lib/chem/db/xyz.rb +39 -0
 - data/lib/chem/model.rb +119 -0
 - data/lib/chem/model/skeleton.rb +37 -0
 - data/lib/chem/utils.rb +11 -0
 - data/lib/chem/utils/geometry.rb +27 -0
 - data/lib/chem/utils/graph_db.rb +146 -0
 - data/lib/chem/utils/math.rb +17 -0
 - data/lib/chem/utils/prop.rb +123 -0
 - data/lib/chem/utils/sssr.rb +101 -0
 - data/lib/chem/utils/sub.rb +78 -0
 - data/lib/chem/utils/transform.rb +110 -0
 - data/lib/chem/utils/traverse.rb +37 -0
 - data/lib/chem/utils/ullmann.rb +134 -0
 - data/lib/graph.rb +41 -0
 - data/lib/graph/cluster.rb +20 -0
 - data/lib/graph/morgan.rb +38 -0
 - data/sample/frequent_subgraph.rb +46 -0
 - data/sample/images/ex1.rb +11 -0
 - data/sample/images/ex2.rb +4 -0
 - data/sample/images/ex3.rb +5 -0
 - data/sample/images/ex4.rb +17 -0
 - data/sample/images/ex5.rb +10 -0
 - data/sample/images/mol/adenine.mol +26 -0
 - data/sample/images/mol/atp.mol +69 -0
 - data/sample/images/temp/ex5.mol +344 -0
 - data/sample/kegg_db.rb +116 -0
 - data/setup.rb +1551 -0
 - data/test/all.rb +6 -0
 - data/test/coord_test.rb +17 -0
 - data/test/ctab_test.rb +31 -0
 - data/test/data/A_21.tar.gz +0 -0
 - data/test/data/A_21/aceanthrylene.cdx +0 -0
 - data/test/data/A_21/aceanthrylene.mol +40 -0
 - data/test/data/A_21/acenaphthylene.cdx +0 -0
 - data/test/data/A_21/acenaphthylene.mol +31 -0
 - data/test/data/A_21/acephenanthrylene.cdx +0 -0
 - data/test/data/A_21/acephenanthrylene.mol +40 -0
 - data/test/data/A_21/anthracene.cdx +0 -0
 - data/test/data/A_21/anthracene.mol +35 -0
 - data/test/data/A_21/as-indacene.cdx +0 -0
 - data/test/data/A_21/as-indacene.mol +31 -0
 - data/test/data/A_21/azulene.cdx +0 -0
 - data/test/data/A_21/azulene.mol +26 -0
 - data/test/data/A_21/biphenylene.cdx +0 -0
 - data/test/data/A_21/biphenylene.mol +31 -0
 - data/test/data/A_21/chrysene.cdx +0 -0
 - data/test/data/A_21/chrysene.mol +44 -0
 - data/test/data/A_21/coronen.cdx +0 -0
 - data/test/data/A_21/coronen.mol +59 -0
 - data/test/data/A_21/fluoranthene.cdx +0 -0
 - data/test/data/A_21/fluoranthene.mol +40 -0
 - data/test/data/A_21/fluorene.cdx +0 -0
 - data/test/data/A_21/fluorene.mol +33 -0
 - data/test/data/A_21/heptacene.cdx +0 -0
 - data/test/data/A_21/heptacene.mol +71 -0
 - data/test/data/A_21/heptalene.cdx +0 -0
 - data/test/data/A_21/heptalene.mol +30 -0
 - data/test/data/A_21/heptaphene.cdx +0 -0
 - data/test/data/A_21/heptaphene.mol +71 -0
 - data/test/data/A_21/hexacene.cdx +0 -0
 - data/test/data/A_21/hexacene.mol +62 -0
 - data/test/data/A_21/hexaphene.cdx +0 -0
 - data/test/data/A_21/hexaphene.mol +62 -0
 - data/test/data/A_21/indene.cdx +0 -0
 - data/test/data/A_21/indene.mol +24 -0
 - data/test/data/A_21/iupac.txt +41 -0
 - data/test/data/A_21/naphthacene.cdx +0 -0
 - data/test/data/A_21/naphthacene.mol +44 -0
 - data/test/data/A_21/naphthalene.cdx +0 -0
 - data/test/data/A_21/naphthalene.mol +26 -0
 - data/test/data/A_21/ovalene.cdx +0 -0
 - data/test/data/A_21/ovalene.mol +78 -0
 - data/test/data/A_21/pentacene.cdx +0 -0
 - data/test/data/A_21/pentacene.mol +53 -0
 - data/test/data/A_21/pentalene.cdx +0 -0
 - data/test/data/A_21/pentalene.mol +22 -0
 - data/test/data/A_21/pentaphene.cdx +0 -0
 - data/test/data/A_21/pentaphene.mol +53 -0
 - data/test/data/A_21/perylene.cdx +0 -0
 - data/test/data/A_21/perylene.mol +49 -0
 - data/test/data/A_21/phenalene.cdx +0 -0
 - data/test/data/A_21/phenalene.mol +33 -0
 - data/test/data/A_21/phenanthrene.cdx +0 -0
 - data/test/data/A_21/phenanthrene.mol +35 -0
 - data/test/data/A_21/picene.cdx +0 -0
 - data/test/data/A_21/picene.mol +53 -0
 - data/test/data/A_21/pleiadene.cdx +0 -0
 - data/test/data/A_21/pleiadene.mol +44 -0
 - data/test/data/A_21/pyranthrene.cdx +0 -0
 - data/test/data/A_21/pyranthrene.mol +72 -0
 - data/test/data/A_21/pyrene.cdx +0 -0
 - data/test/data/A_21/pyrene.mol +40 -0
 - data/test/data/A_21/rubicene.cdx +0 -0
 - data/test/data/A_21/rubicene.mol +63 -0
 - data/test/data/A_21/s-indacene.cdx +0 -0
 - data/test/data/A_21/s-indacene.mol +31 -0
 - data/test/data/A_21/tetraphenylene.cdx +0 -0
 - data/test/data/A_21/tetraphenylene.mol +57 -0
 - data/test/data/A_21/trinaphthylene.cdx +0 -0
 - data/test/data/A_21/trinaphthylene.mol +71 -0
 - data/test/data/A_21/triphenylene.cdx +0 -0
 - data/test/data/A_21/triphenylene.mol +44 -0
 - data/test/data/C00147.kcf +25 -0
 - data/test/data/G00147.kcf +13 -0
 - data/test/data/atp.mol +69 -0
 - data/test/data/cyclohexane.mol +17 -0
 - data/test/data/cyclohexane.ps +485 -0
 - data/test/data/fullerene.mol +155 -0
 - data/test/data/glycan +33 -0
 - data/test/data/hypericin.cdx +0 -0
 - data/test/data/hypericin.cdxml +596 -0
 - data/test/data/hypericin.chm +0 -0
 - data/test/data/hypericin.ct +85 -0
 - data/test/data/hypericin.f1d +0 -0
 - data/test/data/hypericin.f1q +0 -0
 - data/test/data/hypericin.gif +0 -0
 - data/test/data/hypericin.mol +88 -0
 - data/test/data/hypericin.mol2 +159 -0
 - data/test/data/hypericin.msm +123 -0
 - data/test/data/hypericin.pdf +359 -0
 - data/test/data/hypericin.png +0 -0
 - data/test/data/hypericin.ps +0 -0
 - data/test/data/hypericin.skc +0 -0
 - data/test/data/hypericin2.gif +0 -0
 - data/test/data/hypericin2.ps +0 -0
 - data/test/data/kegg/genomes/hsa/hsa_enzyme.list +4 -0
 - data/test/data/kegg/genomes/hsa/hsa_pfam.list +4 -0
 - data/test/data/kegg/ligand/mol/C00147.mol +26 -0
 - data/test/data/kegg/ligand/reaction +14 -0
 - data/test/data/kegg/ligand/reaction.lst +1 -0
 - data/test/data/kegg/ligand/reaction_mapformula.lst +3 -0
 - data/test/data/reaction +14 -0
 - data/test/data/reaction.lst +1 -0
 - data/test/data/reaction_mapformula.lst +3 -0
 - data/test/data/rxn/C00001.mol +6 -0
 - data/test/data/rxn/C00011.mol +10 -0
 - data/test/data/rxn/C00014.mol +6 -0
 - data/test/data/rxn/C01010.mol +18 -0
 - data/test/data/rxn/sample.rxn +50 -0
 - data/test/data/rxn/substitution.rxn +45 -0
 - data/test/data/test.eps +0 -0
 - data/test/data/test.mol +28 -0
 - data/test/data/test.sdf +143 -0
 - data/test/data/test.skc +0 -0
 - data/test/data/test.xyz +4 -0
 - data/test/data/test_lf.sdf +143 -0
 - data/test/heavy_test_pubchem.rb +16 -0
 - data/test/multiple_test.rb +22 -0
 - data/test/test_adj.rb +54 -0
 - data/test/test_canonical_smiles.rb +46 -0
 - data/test/test_cdx.rb +32 -0
 - data/test/test_chem.rb +18 -0
 - data/test/test_cluster.rb +19 -0
 - data/test/test_db.rb +11 -0
 - data/test/test_eps.rb +24 -0
 - data/test/test_geometry.rb +11 -0
 - data/test/test_gspan.rb +28 -0
 - data/test/test_iupac.rb +36 -0
 - data/test/test_kcf.rb +24 -0
 - data/test/test_kcf_glycan.rb +10 -0
 - data/test/test_kegg.rb +118 -0
 - data/test/test_linucs.rb +21 -0
 - data/test/test_mdl.rb +45 -0
 - data/test/test_mol2.rb +62 -0
 - data/test/test_morgan.rb +21 -0
 - data/test/test_pdf.rb +12 -0
 - data/test/test_prop.rb +86 -0
 - data/test/test_rmagick.rb +15 -0
 - data/test/test_sbdb.rb +23 -0
 - data/test/test_sdf.rb +30 -0
 - data/test/test_smiles.rb +84 -0
 - data/test/test_sssr.rb +18 -0
 - data/test/test_sub.rb +47 -0
 - data/test/test_subcomp.rb +37 -0
 - data/test/test_traverse.rb +29 -0
 - data/test/test_writer.rb +13 -0
 - data/test/test_xyz.rb +15 -0
 - data/test/type_test.rb +25 -0
 - metadata +290 -0
 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require 'matrix'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            class Vector
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def []=(i,x) ; @elements[i]=x  ;  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              def x        ; @elements[0]    ; end
         
     | 
| 
      
 9 
     | 
    
         
            +
              def y        ; @elements[1]    ; end
         
     | 
| 
      
 10 
     | 
    
         
            +
              def z        ; @elements[2]    ; end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def x= x_val ; @elements[0] = x_val ; end
         
     | 
| 
      
 13 
     | 
    
         
            +
              def y= y_val ; @elements[1] = y_val ; end
         
     | 
| 
      
 14 
     | 
    
         
            +
              def z= z_val ; @elements[2] = z_val ; end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,123 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # module for calculating properties
         
     | 
| 
      
 3 
     | 
    
         
            +
            #
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Chem
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              module Atom
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # Returns electro negativity
         
     | 
| 
      
 10 
     | 
    
         
            +
                # see chem/data/electronegativity.rb
         
     | 
| 
      
 11 
     | 
    
         
            +
                def electro_negativity
         
     | 
| 
      
 12 
     | 
    
         
            +
                  ElectroNegativity[self.element]
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                # Returns Natural Bond Order of this atom
         
     | 
| 
      
 16 
     | 
    
         
            +
                # :C => 4, :H => 1...
         
     | 
| 
      
 17 
     | 
    
         
            +
                # see chem/data/character.rb
         
     | 
| 
      
 18 
     | 
    
         
            +
                def natural_bond_order
         
     | 
| 
      
 19 
     | 
    
         
            +
                  NaturalBondOrder[self.element]
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                # Returns Atomic weight
         
     | 
| 
      
 23 
     | 
    
         
            +
                # see chem/data/atomic_weight.rb
         
     | 
| 
      
 24 
     | 
    
         
            +
                def weight
         
     | 
| 
      
 25 
     | 
    
         
            +
                  AtomicWeight[self.element]
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              module Molecule
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                # Returns number of hydrogen
         
     | 
| 
      
 33 
     | 
    
         
            +
                # this method may be overrided
         
     | 
| 
      
 34 
     | 
    
         
            +
                def n_hydrogen node
         
     | 
| 
      
 35 
     | 
    
         
            +
                  n_h = node.natural_bond_order
         
     | 
| 
      
 36 
     | 
    
         
            +
                  adjacent_to(node).each do |bond, atom|
         
     | 
| 
      
 37 
     | 
    
         
            +
                    n_h -= bond.v
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  n_h
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                # Returns molecular weight
         
     | 
| 
      
 43 
     | 
    
         
            +
                # mol.molecular_weight :unknown_atom => true
         
     | 
| 
      
 44 
     | 
    
         
            +
                def molecular_weight prop = {}
         
     | 
| 
      
 45 
     | 
    
         
            +
                  comp = self.composition()
         
     | 
| 
      
 46 
     | 
    
         
            +
                  comp.inject(0.0){|ret, (el, n)|
         
     | 
| 
      
 47 
     | 
    
         
            +
                    if AtomicWeight[el]
         
     | 
| 
      
 48 
     | 
    
         
            +
                      ret + AtomicWeight[el] * n
         
     | 
| 
      
 49 
     | 
    
         
            +
                    elsif prop[:neglect_unknown_atom]
         
     | 
| 
      
 50 
     | 
    
         
            +
                      ret
         
     | 
| 
      
 51 
     | 
    
         
            +
                    else
         
     | 
| 
      
 52 
     | 
    
         
            +
                      return nil
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  }
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                alias mw molecular_weight
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                # Returns oxidation number of node
         
     | 
| 
      
 60 
     | 
    
         
            +
                # this method can be moved to Atom module
         
     | 
| 
      
 61 
     | 
    
         
            +
                def oxidation_number node
         
     | 
| 
      
 62 
     | 
    
         
            +
                  en = 0
         
     | 
| 
      
 63 
     | 
    
         
            +
                  adjacent_to(node).each do |bond, atom|
         
     | 
| 
      
 64 
     | 
    
         
            +
                    case node.electro_negativity <=> atom.electro_negativity
         
     | 
| 
      
 65 
     | 
    
         
            +
                    when -1
         
     | 
| 
      
 66 
     | 
    
         
            +
                      en += bond.v
         
     | 
| 
      
 67 
     | 
    
         
            +
                    when 1
         
     | 
| 
      
 68 
     | 
    
         
            +
                      en -= bond.v
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                  # implicit hydrogen
         
     | 
| 
      
 72 
     | 
    
         
            +
                  if ElectroNegativity[:H] < node.electro_negativity
         
     | 
| 
      
 73 
     | 
    
         
            +
                    en -= n_hydrogen(node)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  else
         
     | 
| 
      
 75 
     | 
    
         
            +
                    en += n_hydrogen(node)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                  en
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                # Returns composition
         
     | 
| 
      
 81 
     | 
    
         
            +
                # Chem.open_mol("benzene").composition # {:C => 6, :H => 6}
         
     | 
| 
      
 82 
     | 
    
         
            +
                def composition
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  composition = {}
         
     | 
| 
      
 85 
     | 
    
         
            +
                  @nodes.each do |atom|
         
     | 
| 
      
 86 
     | 
    
         
            +
                    composition[atom.element] ||= 0
         
     | 
| 
      
 87 
     | 
    
         
            +
                    composition[atom.element] += 1
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
                  composition
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                # return     1 if self.composition >  to.composition
         
     | 
| 
      
 93 
     | 
    
         
            +
                # return     0 if self.composition == to.composition
         
     | 
| 
      
 94 
     | 
    
         
            +
                # return    -1 if self.composition <  to.composition
         
     | 
| 
      
 95 
     | 
    
         
            +
                # return false if self.composition <> to.composition
         
     | 
| 
      
 96 
     | 
    
         
            +
                def subset_in_composition?(to)
         
     | 
| 
      
 97 
     | 
    
         
            +
                  self_is_sub = false
         
     | 
| 
      
 98 
     | 
    
         
            +
                  to_is_sub   = false
         
     | 
| 
      
 99 
     | 
    
         
            +
                  all = (to.composition.keys + composition.keys).uniq
         
     | 
| 
      
 100 
     | 
    
         
            +
                  return false if all.length == 0
         
     | 
| 
      
 101 
     | 
    
         
            +
                  if (all - composition.keys).length > 0 && (all - to.composition.keys).length > 0
         
     | 
| 
      
 102 
     | 
    
         
            +
                    return false
         
     | 
| 
      
 103 
     | 
    
         
            +
                  elsif (all - composition.keys).length > 0
         
     | 
| 
      
 104 
     | 
    
         
            +
                    return -1 if composition.all?{|k, v| v <= to.composition[k]}
         
     | 
| 
      
 105 
     | 
    
         
            +
                    return false
         
     | 
| 
      
 106 
     | 
    
         
            +
                  elsif (all - to.composition.keys).length > 0
         
     | 
| 
      
 107 
     | 
    
         
            +
                    return 1 if to.composition.all?{|k, v| v <= composition[k]}
         
     | 
| 
      
 108 
     | 
    
         
            +
                    return false
         
     | 
| 
      
 109 
     | 
    
         
            +
                  elsif all.length == composition.keys.length && all.length == to.composition.length
         
     | 
| 
      
 110 
     | 
    
         
            +
                    # then compare number of nodes ?
         
     | 
| 
      
 111 
     | 
    
         
            +
                    if all.all? { |node| composition[node] == to.composition[node]}
         
     | 
| 
      
 112 
     | 
    
         
            +
                      return 0
         
     | 
| 
      
 113 
     | 
    
         
            +
                    elsif all.all?{ |node| composition[node] >= to.composition[node]}
         
     | 
| 
      
 114 
     | 
    
         
            +
                      return 1
         
     | 
| 
      
 115 
     | 
    
         
            +
                    elsif all.all?{ |node| composition[node] <= to.composition[node]}
         
     | 
| 
      
 116 
     | 
    
         
            +
                      return -1
         
     | 
| 
      
 117 
     | 
    
         
            +
                    end
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
                  return false
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,101 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Chem
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Ring
         
     | 
| 
      
 5 
     | 
    
         
            +
              end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              module Molecule
         
     | 
| 
      
 8 
     | 
    
         
            +
                # J. Chem. Inf. Comput. Sci. 1996, 36, 986-991
         
     | 
| 
      
 9 
     | 
    
         
            +
                # John Figueras
         
     | 
| 
      
 10 
     | 
    
         
            +
                # Ring Perception Using Breadth-First Search
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                # J. Chem. Inf. Comput. Sci. 1994, 34, 822-831
         
     | 
| 
      
 13 
     | 
    
         
            +
                # Renzo Balducci and Robert S. Pearlman
         
     | 
| 
      
 14 
     | 
    
         
            +
                # Efficient Exact Solution of the Ring Perception Problem
         
     | 
| 
      
 15 
     | 
    
         
            +
                #
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def find_smallest_ring root
         
     | 
| 
      
 18 
     | 
    
         
            +
                  path = {}
         
     | 
| 
      
 19 
     | 
    
         
            +
                  path[root] = [root]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  bfs(root) do |from, to|
         
     | 
| 
      
 22 
     | 
    
         
            +
            	if visit = !path.keys.include?(to)
         
     | 
| 
      
 23 
     | 
    
         
            +
            	  path[to] = path[from].clone
         
     | 
| 
      
 24 
     | 
    
         
            +
            	  path[to].push(to)
         
     | 
| 
      
 25 
     | 
    
         
            +
            	elsif path[from][-2] != to
         
     | 
| 
      
 26 
     | 
    
         
            +
            	  if 1 == (path[from] & path[to]).length
         
     | 
| 
      
 27 
     | 
    
         
            +
            	    return path[from] + path[to][1..-1].reverse
         
     | 
| 
      
 28 
     | 
    
         
            +
            	  end
         
     | 
| 
      
 29 
     | 
    
         
            +
            	end
         
     | 
| 
      
 30 
     | 
    
         
            +
            	visit
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def canonical_ring ring
         
     | 
| 
      
 35 
     | 
    
         
            +
            #      ring.sort # Fix me! This is not sufficient
         
     | 
| 
      
 36 
     | 
    
         
            +
                  ring.sort{|a, b| @atoms.index(a) <=> @atoms.index(b)}
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def find_sssr
         
     | 
| 
      
 40 
     | 
    
         
            +
                  return @sssr if @sssr
         
     | 
| 
      
 41 
     | 
    
         
            +
                  fullSet = []
         
     | 
| 
      
 42 
     | 
    
         
            +
                  trimSet = []
         
     | 
| 
      
 43 
     | 
    
         
            +
                  rings = []
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @mol = {}
         
     | 
| 
      
 45 
     | 
    
         
            +
            #     mol = {1=>[2, 5], 2=> [1, 3], 3=> [2, 4], 4=>[3, 5], 5=>[4,1]}
         
     | 
| 
      
 46 
     | 
    
         
            +
            #       @nodes.each do |k, atom|
         
     | 
| 
      
 47 
     | 
    
         
            +
            # 	atom.set_neighbor
         
     | 
| 
      
 48 
     | 
    
         
            +
            # 	@mol[atom] = atom.neighbor
         
     | 
| 
      
 49 
     | 
    
         
            +
            #       end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 52 
     | 
    
         
            +
            	nodesN2 = []
         
     | 
| 
      
 53 
     | 
    
         
            +
            	smallest_degree = 10
         
     | 
| 
      
 54 
     | 
    
         
            +
            	smallest = nil
         
     | 
| 
      
 55 
     | 
    
         
            +
            	@mol.each do |k, a|
         
     | 
| 
      
 56 
     | 
    
         
            +
            	  case a.length
         
     | 
| 
      
 57 
     | 
    
         
            +
            	  when 0
         
     | 
| 
      
 58 
     | 
    
         
            +
            	    @mol.delete(k)# Is this OK?
         
     | 
| 
      
 59 
     | 
    
         
            +
            	    trimSet.push(k)
         
     | 
| 
      
 60 
     | 
    
         
            +
            	  when 2
         
     | 
| 
      
 61 
     | 
    
         
            +
            	    nodesN2.push(k)
         
     | 
| 
      
 62 
     | 
    
         
            +
            	  end
         
     | 
| 
      
 63 
     | 
    
         
            +
            	  if a.length > 0 && a.length < smallest_degree
         
     | 
| 
      
 64 
     | 
    
         
            +
            	    smallest = k
         
     | 
| 
      
 65 
     | 
    
         
            +
            	    smallest_degree = a.length
         
     | 
| 
      
 66 
     | 
    
         
            +
            	  end
         
     | 
| 
      
 67 
     | 
    
         
            +
            	end
         
     | 
| 
      
 68 
     | 
    
         
            +
            	case smallest_degree
         
     | 
| 
      
 69 
     | 
    
         
            +
            	when 1
         
     | 
| 
      
 70 
     | 
    
         
            +
            	  trim(smallest)
         
     | 
| 
      
 71 
     | 
    
         
            +
            	when 2
         
     | 
| 
      
 72 
     | 
    
         
            +
            	  nodesN2.each do |k|
         
     | 
| 
      
 73 
     | 
    
         
            +
            	    ring = find_smallest_ring(k)
         
     | 
| 
      
 74 
     | 
    
         
            +
            #	    rings.push(canonical_ring(ring)) if !rings.include?(canonical_ring(ring))
         
     | 
| 
      
 75 
     | 
    
         
            +
            	    rings.push(canonical_ring(ring)) if ring && !rings.include?(canonical_ring(ring))
         
     | 
| 
      
 76 
     | 
    
         
            +
            	  end
         
     | 
| 
      
 77 
     | 
    
         
            +
            	  nodesN2.each do |k|
         
     | 
| 
      
 78 
     | 
    
         
            +
            	    trim(k)
         
     | 
| 
      
 79 
     | 
    
         
            +
            	  end
         
     | 
| 
      
 80 
     | 
    
         
            +
            	when 3
         
     | 
| 
      
 81 
     | 
    
         
            +
            	  ring = find_smallest_ring(smallest)
         
     | 
| 
      
 82 
     | 
    
         
            +
            	  trim(smallest)
         
     | 
| 
      
 83 
     | 
    
         
            +
            	end
         
     | 
| 
      
 84 
     | 
    
         
            +
            	break if @mol.length  == 0
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
                  @sssr = rings
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                def trim smallest
         
     | 
| 
      
 90 
     | 
    
         
            +
                  if @mol.length > 0 && @mol.include?(smallest)
         
     | 
| 
      
 91 
     | 
    
         
            +
            	@mol[smallest].each do |n|
         
     | 
| 
      
 92 
     | 
    
         
            +
            	  @mol[n] = @mol[n] - [smallest]
         
     | 
| 
      
 93 
     | 
    
         
            +
            	  @mol.delete(smallest)
         
     | 
| 
      
 94 
     | 
    
         
            +
            	  @mol.delete(n) if @mol[n].length == 0
         
     | 
| 
      
 95 
     | 
    
         
            +
            	end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
              end
         
     | 
| 
      
 100 
     | 
    
         
            +
            end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,78 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Chem
         
     | 
| 
      
 3 
     | 
    
         
            +
              module Molecule
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def induced_sub ary
         
     | 
| 
      
 6 
     | 
    
         
            +
                  sub = deep_dup
         
     | 
| 
      
 7 
     | 
    
         
            +
                  (sub.nodes - ary).each do |node|
         
     | 
| 
      
 8 
     | 
    
         
            +
                    sub.delete(node)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
                  sub
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def connected?
         
     | 
| 
      
 14 
     | 
    
         
            +
                  traversed = []
         
     | 
| 
      
 15 
     | 
    
         
            +
                  start = @nodes[0]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  traversed << start
         
     | 
| 
      
 17 
     | 
    
         
            +
                  dfs(start) do |from, to|
         
     | 
| 
      
 18 
     | 
    
         
            +
                    traversed << to
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  traversed.length == @nodes.length
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # divide compounds by connectivity
         
     | 
| 
      
 24 
     | 
    
         
            +
                # e.g. washing salts.
         
     | 
| 
      
 25 
     | 
    
         
            +
                def divide
         
     | 
| 
      
 26 
     | 
    
         
            +
                  traversed = []
         
     | 
| 
      
 27 
     | 
    
         
            +
                  start = @nodes[0]
         
     | 
| 
      
 28 
     | 
    
         
            +
                  divided_compound = []
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  while traversed.length != @nodes.length
         
     | 
| 
      
 31 
     | 
    
         
            +
                    part = []
         
     | 
| 
      
 32 
     | 
    
         
            +
                    traversed << start
         
     | 
| 
      
 33 
     | 
    
         
            +
                    part << start
         
     | 
| 
      
 34 
     | 
    
         
            +
                    dfs(start) do |from, to, bond|
         
     | 
| 
      
 35 
     | 
    
         
            +
                      unless part.include?(to)
         
     | 
| 
      
 36 
     | 
    
         
            +
                        traversed << to
         
     | 
| 
      
 37 
     | 
    
         
            +
                        part << to
         
     | 
| 
      
 38 
     | 
    
         
            +
                      end
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    start = @nodes.find{|node| !traversed.include?(node)}
         
     | 
| 
      
 42 
     | 
    
         
            +
                    divided_compound << induced_sub(part)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  divided_compound
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                def delete_bond(bond)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @edges.delete(bond)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @adjacencies.each do |v, k|
         
     | 
| 
      
 50 
     | 
    
         
            +
                    k.delete_if{ |b, atom_a, atom_b| bond == b}
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def delete(atom)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @nodes.delete(atom)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  adjacent_to(atom).each do |adj_edge, adj_node|
         
     | 
| 
      
 57 
     | 
    
         
            +
                    @edges.delete_if{|bond, atom_a, atom_b| bond == adj_edge}
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def deep_dup
         
     | 
| 
      
 62 
     | 
    
         
            +
                  ret = dup
         
     | 
| 
      
 63 
     | 
    
         
            +
                  ret.nodes = @nodes.dup
         
     | 
| 
      
 64 
     | 
    
         
            +
                  #ret.adjacencies = @adjacencies.dup if @adjacencies
         
     | 
| 
      
 65 
     | 
    
         
            +
                  ret.edges = @edges.dup
         
     | 
| 
      
 66 
     | 
    
         
            +
                  ret
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def - (other)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  if other.instance_of?(Array)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    induced_sub(@nodes - other)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  else
         
     | 
| 
      
 73 
     | 
    
         
            +
                    induced_sub(@nodes - other.nodes)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,110 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/local/bin/ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'matrix'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Chem
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              module Transform
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                module TwoDimension
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 12 
     | 
    
         
            +
                    super
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @pos = Vector[0.0, 0.0]
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def pos ; @pos ||= Vector[@x, @y, @z] ; end
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def x ; pos[0] ; end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  def y ; pos[1] ; end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  def x=(x_val) ; pos[0] = x_val ; end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  def y=(y_val) ; pos[1] = y_val ; end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                module ThreeDimension
         
     | 
| 
      
 24 
     | 
    
         
            +
                  include TwoDimension
         
     | 
| 
      
 25 
     | 
    
         
            +
                  
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 27 
     | 
    
         
            +
                    super
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @pos = Vector[0.0, 0.0]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def z ; pos[2] ; end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  def z=(z_val) ; pos[2] = z_val ; end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            class Transform
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              def initialize m = Matrix.new
         
     | 
| 
      
 42 
     | 
    
         
            +
                @m = m
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              def * (t)
         
     | 
| 
      
 46 
     | 
    
         
            +
                @m * t
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              def transform(v)
         
     | 
| 
      
 50 
     | 
    
         
            +
                v * @m
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              def Transform::translate(x, y, z)
         
     | 
| 
      
 54 
     | 
    
         
            +
                Matrix[[1, 0, 0, 0],
         
     | 
| 
      
 55 
     | 
    
         
            +
                       [0, 1, 0, 0],
         
     | 
| 
      
 56 
     | 
    
         
            +
                       [0, 0, 1, 0],
         
     | 
| 
      
 57 
     | 
    
         
            +
                       [x, y, z, 1]].transpose
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              def Transform::scale(x, y, z)
         
     | 
| 
      
 61 
     | 
    
         
            +
                Matrix[[x, 0, 0, 0],
         
     | 
| 
      
 62 
     | 
    
         
            +
                       [0, y, 0, 0],
         
     | 
| 
      
 63 
     | 
    
         
            +
                       [0, 0, z, 0],
         
     | 
| 
      
 64 
     | 
    
         
            +
                       [0, 0, 0, 1]].transpose
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              def Transform::rotate_x(theta)
         
     | 
| 
      
 68 
     | 
    
         
            +
                Matrix[[1.0,               0.0,             0.0, 0.0],
         
     | 
| 
      
 69 
     | 
    
         
            +
                       [0.0,   Math.cos(theta), Math.sin(theta), 0.0],
         
     | 
| 
      
 70 
     | 
    
         
            +
                       [0.0, - Math.sin(theta), Math.cos(theta), 0.0],
         
     | 
| 
      
 71 
     | 
    
         
            +
                       [0.0,               0.0,             0.0, 1.0]].transpose
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
              def Transform::rotate_y(theta)
         
     | 
| 
      
 75 
     | 
    
         
            +
                Matrix[[Math.cos(theta),   0.0, - Math.sin(theta), 0.0],
         
     | 
| 
      
 76 
     | 
    
         
            +
                       [0.0,               1.0,               0.0, 0.0],
         
     | 
| 
      
 77 
     | 
    
         
            +
                       [Math.sin(theta),   0.0,   Math.cos(theta), 0.0],
         
     | 
| 
      
 78 
     | 
    
         
            +
                       [0.0,               0.0,               0.0, 1.0]].transpose
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
              def Transform::rotate_z(theta)
         
     | 
| 
      
 82 
     | 
    
         
            +
                Matrix[[  Math.cos(theta),   Math.sin(theta),   0.0, 0.0],
         
     | 
| 
      
 83 
     | 
    
         
            +
                       [- Math.sin(theta),   Math.cos(theta),   0.0, 0.0],
         
     | 
| 
      
 84 
     | 
    
         
            +
                       [  0.0,               0.0,               1.0, 0.0],
         
     | 
| 
      
 85 
     | 
    
         
            +
                       [  0.0,               0.0,               0.0, 1.0]].transpose
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
              def Transform::inverse_x
         
     | 
| 
      
 89 
     | 
    
         
            +
                Matrix[[ -1,  0,  0,  0],
         
     | 
| 
      
 90 
     | 
    
         
            +
                       [  0,  1,  0,  0],
         
     | 
| 
      
 91 
     | 
    
         
            +
                       [  0,  0, -1,  0],
         
     | 
| 
      
 92 
     | 
    
         
            +
                       [  0,  0,  0,  1]].transpose
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
              def Transform::inverse_y
         
     | 
| 
      
 96 
     | 
    
         
            +
                Matrix[[  1,  0,  0,  0],
         
     | 
| 
      
 97 
     | 
    
         
            +
                       [  0, -1,  0,  0],
         
     | 
| 
      
 98 
     | 
    
         
            +
                       [  0,  0,  1,  0],
         
     | 
| 
      
 99 
     | 
    
         
            +
                       [  0,  0,  0,  1]].transpose
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
              def Transform::inverse_z
         
     | 
| 
      
 103 
     | 
    
         
            +
                Matrix[[  1,  0,  0,  0],
         
     | 
| 
      
 104 
     | 
    
         
            +
                       [  0,  1,  0,  0],
         
     | 
| 
      
 105 
     | 
    
         
            +
                       [  0,  0, -1,  0],
         
     | 
| 
      
 106 
     | 
    
         
            +
                       [  0,  0,  0,  1]].transpose
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
            end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            module Chem
         
     | 
| 
      
 3 
     | 
    
         
            +
              module Molecule
         
     | 
| 
      
 4 
     | 
    
         
            +
                # Breadth first search solves steps and path to the each node and forms
         
     | 
| 
      
 5 
     | 
    
         
            +
                # a tree contains all reachable vertices from the root node.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                def breadth_first_search(root = @nodes[0])
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  queue = [ root ]
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  traversed = []
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  while from = queue.shift
         
     | 
| 
      
 14 
     | 
    
         
            +
            	adjacent_to(from).each do |bond, to|
         
     | 
| 
      
 15 
     | 
    
         
            +
                      next if traversed.include?(bond)
         
     | 
| 
      
 16 
     | 
    
         
            +
                      traversed.push(bond)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      queue.push(to) if yield(from, to)
         
     | 
| 
      
 18 
     | 
    
         
            +
            	end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                alias :bfs :breadth_first_search
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def depth_first_search(from = @nodes[0], traversed = [], &block)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  adjacent_to(from).each do |bond, to|
         
     | 
| 
      
 26 
     | 
    
         
            +
                    next if traversed.include?(bond)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    traversed.push(bond)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    yield(from, to, bond)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    depth_first_search(to, traversed, &block)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                alias :dfs :depth_first_search
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     |