├── LICENSE
├── README.md
├── __init__.py
├── data
├── __init__.py
├── download_data.py
├── qm9_config.txt
├── qm9_kekulized_ggnp.txt
├── transform_qm9.py
├── transform_zinc250k.py
├── valid_idx_qm9.json
├── valid_idx_zinc.json
├── zinc250k_config.txt
└── zinc250k_kekulized_ggnp.txt
├── framework.png
├── graph_nvp
├── __init__.py
├── coupling.py
├── hyperparams.py
├── mlp.py
├── nvp_model.py
└── rgcn.py
├── train.sh
├── train_mle.py
└── utils
├── __init__.py
├── argparser.py
├── data_utils.py
├── environment.py
├── fpscores.pkl.gz
├── molecular_metrics.py
└── sascorer.py
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Hanlin Zhang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GraphNVP: An Invertible Flow Model for Generating Molecular Graphs
2 |
3 | Implementation of GraphNVP(https://arxiv.org/abs/1905.11600) using PyTorch.
4 |
5 |
6 |
7 |
8 |
9 | ## Data Preparation
10 | `python ./data/download_data.py --data_name=qm9`
11 |
12 | `python ./data/download_data.py --data_name=zinc250k`
13 |
14 | ## Train GraphNVP
15 | `bash ./train.sh`
16 |
17 | ## Citation
18 | ```
19 | @misc{madhawa2019graphnvp,
20 | title={GraphNVP: An Invertible Flow Model for Generating Molecular Graphs},
21 | author={Kaushalya Madhawa and Katushiko Ishiguro and Kosuke Nakago and Motoki Abe},
22 | year={2019},
23 | eprint={1905.11600},
24 | archivePrefix={arXiv},
25 | primaryClass={stat.ML}
26 | }
27 | ```
28 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hlzhang109/PyTorch-GraphNVP/eb6cabd1e5e39f84ffe92662ef5d667aa4e30db3/__init__.py
--------------------------------------------------------------------------------
/data/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hlzhang109/PyTorch-GraphNVP/eb6cabd1e5e39f84ffe92662ef5d667aa4e30db3/data/__init__.py
--------------------------------------------------------------------------------
/data/download_data.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import os
3 |
4 | from chainer_chemistry import datasets
5 | from chainer_chemistry.datasets import NumpyTupleDataset
6 | from chainer_chemistry.dataset.preprocessors import RSGCNPreprocessor, GGNNPreprocessor
7 |
8 | '''
9 | From https://github.com/pfnet-research/graph-nvp/tree/master/data
10 | '''
11 |
12 | def parse():
13 | parser = argparse.ArgumentParser(description='')
14 | parser.add_argument('--data_name', type=str, default='qm9',
15 | choices=['qm9', 'zinc250k'],
16 | help='dataset to be downloaded')
17 | parser.add_argument('--data_type', type=str, default='relgcn',
18 | choices=['gcn', 'relgcn'],)
19 | parser.add_argument('--data_dir', type=str, default='./data')
20 | args = parser.parse_args()
21 | return args
22 |
23 | def to_smiles_txt(smiles, path):
24 | with open(path, 'w') as f:
25 | for smile in smiles:
26 | f.write(smile + '\n')
27 |
28 | args = parse()
29 | data_name = args.data_name
30 | data_type = args.data_type
31 | print('args', vars(args))
32 |
33 | if data_name == 'qm9':
34 | max_atoms = 9
35 | elif data_name == 'zinc250k':
36 | max_atoms = 38
37 | else:
38 | raise ValueError("[ERROR] Unexpected value data_name={}".format(data_name))
39 |
40 | if data_type == 'gcn':
41 | preprocessor = RSGCNPreprocessor(out_size=max_atoms)
42 | elif data_type == 'relgcn':
43 | # preprocessor = GGNNPreprocessor(out_size=max_atoms, kekulize=True, return_is_real_node=False)
44 | preprocessor = GGNNPreprocessor(out_size=max_atoms, kekulize=True)
45 | else:
46 | raise ValueError("[ERROR] Unexpected value data_type={}".format(data_type))
47 |
48 | #data_dir = "."
49 | #os.makedirs(data_dir, exist_ok=True)
50 |
51 | if data_name == 'qm9':
52 | dataset, smiles = datasets.get_qm9(preprocessor, return_smiles=True)
53 | elif data_name == 'zinc250k':
54 | dataset, smiles = datasets.get_zinc250k(preprocessor, return_smiles=True)
55 | elif data_name == 'tox21':
56 | dataset, smiles = datasets.get_tox21(preprocessor, return_smiles=True)
57 | else:
58 | raise ValueError("[ERROR] Unexpected value data_name={}".format(data_name))
59 |
60 | to_smiles_txt(smiles, os.path.join(args.data_dir, '{}_kekulized_ggnp.txt'.format(data_name)))
61 | NumpyTupleDataset.save(os.path.join(args.data_dir, '{}_{}_kekulized_ggnp.npz'.format(data_name, data_type)), dataset)
62 |
--------------------------------------------------------------------------------
/data/qm9_config.txt:
--------------------------------------------------------------------------------
1 | {'atom_list': [6, 7, 8, 9, 0], 'freedom': 0, 'node_dim': 5, 'max_size': 9, 'bond_dim': 4}
--------------------------------------------------------------------------------
/data/transform_qm9.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import json
3 |
4 | def one_hot(data, out_size=9, num_max_id=5):
5 | assert data.shape[0] == out_size
6 | b = np.zeros((out_size, num_max_id))
7 | # data = data[data > 0]
8 | # 6 is C: Carbon, we adopt 6:C, 7:N, 8:O, 9:F only. the last place (4) is for padding virtual node.
9 | indices = np.where(data >= 6, data - 6, num_max_id - 1)
10 | b[np.arange(out_size), indices] = 1
11 | # print('[DEBUG] data', data, 'b', b)
12 | return b
13 |
14 | def transform_fn(data):
15 | node, adj, label = data
16 | # convert to one-hot vector
17 | node = one_hot(node).astype(np.float32)
18 | # single, double, triple and no-bond. Note that last channel axis is not connected instead of aromatic bond.
19 | adj = np.concatenate([adj[:3], 1 - np.sum(adj[:3], axis=0, keepdims=True)],
20 | axis=0).astype(np.float32)
21 | return node, adj, label
22 |
23 |
24 | def get_val_ids():
25 | file_path = 'data/valid_idx_qm9.json'
26 | print('loading train/valid split information from: {}'.format(file_path))
27 | with open(file_path) as json_data:
28 | data = json.load(json_data)
29 | val_ids = [int(idx)-1 for idx in data['valid_idxs']]
30 | return val_ids
--------------------------------------------------------------------------------
/data/transform_zinc250k.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | import numpy as np
4 |
5 | zinc250_atomic_num_list = [6, 7, 8, 9, 15, 16, 17, 35, 53, 0] # 0 is for virtual node.
6 | max_atoms = 38
7 | n_bonds = 4
8 |
9 |
10 | def one_hot_zinc250k(data, out_size=38):
11 | num_max_id = len(zinc250_atomic_num_list)
12 | assert data.shape[0] == out_size
13 | b = np.zeros((out_size, num_max_id), dtype=np.float32)
14 | for i in range(out_size):
15 | ind = zinc250_atomic_num_list.index(data[i])
16 | b[i, ind] = 1.
17 | return b
18 |
19 |
20 | def transform_fn_zinc250k(data):
21 | node, adj, label = data
22 | # convert to one-hot vector
23 | # node = one_hot(node).astype(np.float32)
24 | node = one_hot_zinc250k(node).astype(np.float32)
25 | # single, double, triple and no-bond. Note that last channel axis is not connected instead of aromatic bond.
26 | adj = np.concatenate([adj[:3], 1 - np.sum(adj[:3], axis=0, keepdims=True)],
27 | axis=0).astype(np.float32)
28 | return node, adj, label
29 |
30 |
31 | def get_val_ids():
32 | file_path = 'data/valid_idx_zinc.json'
33 | print('loading train/valid split information from: {}'.format(file_path))
34 | with open(file_path) as json_data:
35 | data = json.load(json_data)
36 | val_ids = [idx-1 for idx in data]
37 | return val_ids
38 |
--------------------------------------------------------------------------------
/data/valid_idx_qm9.json:
--------------------------------------------------------------------------------
1 | { "valid_idxs" : [ "007278", "010763", "102219", "052128", "008481", "001924", "105861", "041205", "073853", "118848", "069978", "107256", "119481", "050813", "005396", "025752", "049466", "113387", "038252", "005318", "007882", "130286", "043831", "119218", "077108", "093782", "116420", "082654", "095162", "091152", "133080", "041278", "048023", "095890", "129984", "040706", "009667", "105326", "054227", "124715", "129055", "132545", "087837", "026501", "082981", "133011", "017704", "085474", "077160", "108817", "108648", "092344", "115107", "059400", "107237", "048379", "088853", "028847", "021763", "054845", "120146", "045867", "117803", "019317", "038818", "019343", "107678", "078744", "081030", "008850", "094817", "011431", "047506", "094532", "024652", "093085", "047415", "034124", "009120", "059282", "073964", "023920", "112441", "113700", "024678", "127657", "017803", "060293", "066972", "040052", "089902", "057636", "017863", "046957", "000874", "049436", "064328", "069725", "075801", "079345", "004195", "105816", "117639", "095055", "013582", "041821", "022697", "122288", "085107", "110783", "128262", "111076", "003067", "021403", "071444", "116137", "123121", "070089", "033286", "093464", "003547", "013229", "059524", "091625", "019406", "040946", "007456", "071425", "078444", "083848", "044892", "111722", "049730", "079854", "103425", "055580", "015608", "054341", "123780", "085362", "068908", "006915", "060295", "022995", "004733", "109959", "004959", "048491", "089224", "009313", "079908", "128788", "052213", "026156", "055497", "128311", "113941", "027552", "049917", "003187", "131151", "049482", "078870", "034649", "029562", "090231", "017740", "027322", "038380", "024261", "067723", "043767", "011610", "044355", "066687", "105951", "000732", "048688", "103663", "048799", "052804", "049594", "045821", "089928", "035130", "042953", "121718", "096875", "103621", "095917", "024748", "105511", "052311", "043242", "092237", "085028", "010107", "015004", "128450", "033710", "125831", "100806", "019394", "097895", "043254", "131235", "034984", "003982", "005966", "021198", "048306", "044971", "078738", "118184", "012393", "059966", "117376", "113211", "104232", "032387", "067105", "112483", "016363", "000299", "084150", "105801", "090265", "068566", "095486", "000722", "043799", "015884", "102819", "053178", "019048", "103117", "033939", "020401", "103722", "014019", "063029", "123714", "097293", "110896", "002288", "007750", "072268", "095882", "098111", "131248", "037674", "008124", "050481", "002320", "072496", "079708", "106210", "014425", "112916", "106661", "065525", "003174", "026868", "060813", "129719", "084053", "108768", "115664", "062202", "061104", "102135", "003851", "039059", "086847", "056434", "014054", "039513", "078162", "103024", "035104", "074156", "050869", "038583", "014446", "070543", "036201", "002408", "060292", "067542", "091143", "112802", "037442", "071905", "061355", "023356", "072152", "072312", "107663", "032001", "043211", "079287", "029592", "009217", "131515", "015535", "036384", "101592", "032257", "128375", "098431", "072886", "111886", "037581", "121047", "069163", "102659", "039097", "120666", "016776", "017559", "121359", "006727", "045298", "062325", "076900", "111941", "024359", "065405", "123318", "073182", "043846", "007170", "115804", "002395", "112089", "071179", "038941", "107154", "111376", "075738", "013046", "124017", "098742", "088909", "113624", "100525", "070530", "022769", "121732", "092556", "092156", "074175", "066541", "005010", "059914", "123268", "114463", "006052", "108119", "094191", "009473", "124966", "047517", "085952", "001507", "115247", "028305", "044389", "080410", "124174", "079880", "051531", "099789", "018622", "067171", "063975", "125316", "095372", "059560", "011283", "048885", "016491", "049441", "024613", "097993", "074310", "067119", "003994", "112480", "132000", "041196", "107301", "086361", "074913", "034368", "022141", "103438", "007770", "122503", "075642", "079166", "005469", "068209", "085849", "121195", "080093", "116687", "126063", "052719", "128096", "131017", "009395", "049275", "039953", "022047", "098708", "082446", "085045", "026650", "117676", "111385", "032461", "034461", "098184", "021712", "007832", "107533", "011976", "012281", "085222", "021785", "103856", "105576", "061612", "077822", "123916", "122876", "087364", "042031", "131056", "088625", "064955", "104914", "113402", "068642", "129707", "101508", "059256", "112601", "089904", "069336", "098935", "045069", "060767", "039792", "056136", "087563", "133339", "047670", "077989", "110681", "109777", "062944", "046006", "015294", "092957", "070651", "072901", "096143", "038610", "083464", "060854", "084735", "022370", "049461", "090288", "046497", "114896", "032149", "008985", "100383", "105349", "081894", "034062", "038490", "012445", "068459", "011246", "112046", "053685", "078725", "108364", "073922", "124737", "052412", "043736", "113574", "045297", "020608", "124663", "062592", "115759", "078622", "081437", "017584", "015185", "113826", "004563", "095642", "091943", "036734", "082142", "109101", "041627", "066852", "123464", "015762", "098890", "050908", "048232", "050521", "008118", "004507", "084443", "038493", "090731", "066015", "068719", "001478", "112785", "031759", "123763", "078521", "084058", "049746", "026587", "095650", "029466", "071822", "003085", "103806", "002037", "048455", "009233", "098180", "074823", "105931", "053197", "056770", "043983", "097016", "050367", "036129", "042215", "084819", "041347", "087451", "037805", "002161", "041705", "131752", "116333", "052936", "078219", "077026", "005740", "105829", "011715", "031105", "121175", "126613", "002894", "047372", "087802", "037614", "057497", "081369", "030127", "126154", "104781", "074714", "109813", "002493", "043245", "103481", "040030", "013213", "003893", "113922", "126358", "128730", "012442", "068023", "006222", "106390", "003004", "102860", "099383", "076982", "089103", "089479", "011436", "094907", "059652", "104991", "097971", "070620", "012825", "111344", "008617", "041399", "062186", "071301", "042515", "008363", "034707", "032105", "044723", "034243", "061774", "006572", "047014", "108413", "062837", "091587", "002931", "029915", "131662", "021455", "111800", "090667", "013339", "045092", "044663", "106870", "097742", "086612", "085344", "119081", "105212", "062138", "062286", "012031", "086362", "078254", "109142", "123558", "019244", "079779", "109723", "103519", "132764", "117921", "087144", "030607", "038519", "107820", "074416", "093781", "024831", "052910", "049306", "102816", "109786", "060299", "040153", "029938", "126940", "082568", "094681", "035521", "009508", "051043", "123167", "007249", "061919", "043302", "075830", "002263", "045567", "074101", "125624", "087399", "114108", "045427", "000042", "066363", "039723", "053232", "085489", "035536", "054504", "042475", "075500", "028950", "009823", "068280", "070119", "101023", "118261", "034435", "004630", "011807", "002533", "057765", "077204", "045048", "133802", "082941", "090755", "113628", "128807", "038045", "094451", "016431", "042923", "043652", "079583", "094011", "056928", "129364", "064465", "091444", "133710", "052853", "084644", "110996", "101836", "002062", "127268", "087696", "011929", "048972", "063224", "039817", "095850", "052063", "062577", "119340", "022063", "051910", "120851", "065879", "037948", "045220", "131061", "105647", "106839", "106116", "126870", "032716", "028783", "065837", "071637", "063132", "034780", "107661", "053029", "072967", "105162", "108179", "065429", "108912", "024006", "024379", "109642", "035908", "016557", "004601", "084335", "082812", "066703", "124341", "059635", "117684", "072531", "132465", "076100", "051608", "111765", "106838", "042421", "052473", "048253", "047529", "005765", "082825", "108927", "100763", "014627", "031582", "070484", "062956", "103935", "089469", "050580", "078126", "019402", "041238", "038983", "067540", "087048", "130913", "059737", "000292", "074575", "069296", "004246", "120698", "030426", "035627", "080351", "020476", "111736", "070175", "097312", "000762", "106110", "011934", "038414", "088474", "071283", "057760", "072121", "084617", "058780", "061897", "120784", "021896", "042614", "038860", "069771", "003544", "089690", "005408", "131888", "091629", "079748", "045446", "016285", "061921", "078502", "111507", "098221", "026345", "111197", "023835", "035749", "073193", "048944", "111595", "072545", "017631", "086047", "124252", "102831", "020421", "022799", "084822", "024552", "076869", "122227", "081110", "028498", "053715", "058977", "092489", "086569", "047540", "069692", "105550", "073475", "084592", "118488", "118151", "038538", "071594", "063697", "066735", "039061", "051933", "117492", "070344", "011407", "051643", "042747", "110900", "073111", "044567", "066681", "004133", "039461", "053661", "128727", "076226", "102675", "132042", "089121", "040751", "087537", "036904", "129537", "133566", "081795", "129929", "103082", "076097", "072916", "062248", "061358", "028789", "051841", "097354", "066372", "028784", "026366", "007009", "035919", "081694", "005442", "058232", "055056", "072630", "055828", "087281", "039794", "077265", "038272", "076619", "024729", "067398", "123404", "030057", "102760", "018331", "036763", "005930", "034694", "044633", "084914", "027864", "048072", "112953", "000662", "003783", "102847", "099967", "072763", "058869", "081753", "050667", "025881", "102190", "062429", "004845", "041668", "119958", "007521", "067128", "079498", "108140", "044880", "086255", "115434", "048220", "112506", "023995", "016806", "107538", "091781", "121091", "107579", "089555", "131560", "022273", "065925", "009875", "029080", "053809", "071902", "120654", "108947", "020255", "031962", "012671", "052609", "016292", "051781", "113109", "004911", "123951", "004047", "014275", "025849", "033138", "096033", "104764", "061394", "067476", "049980", "095362", "041699", "079894", "095715", "110093", "015997", "126209", "065897", "131164", "124580", "060318", "124787", "092874", "005474", "052250", "117936", "125168", "033677", "048518", "004100", "003514", "110754", "085025", "121583", "011166", "038271", "125144", "040164", "127440", "096443", "036484", "109973", "110447", "018554", "072835", "007489", "093462", "072741", "096787", "071803", "068093", "085962", "043446", "040535", "122822", "088803", "115071", "047987", "096823", "131116", "031270", "068071", "065621", "128965", "110988", "065912", "089677", "053871", "117068", "080593", "082050", "035243", "106966", "105181", "008068", "020102", "118763", "002281", "006444", "111317", "069188", "064118", "096269", "123690", "063120", "081573", "096166", "116613", "043483", "065198", "033993", "093321", "056896", "106457", "126770", "042198", "013330", "057120", "006490", "095326", "102641", "076782", "106093", "054577", "004756", "080328", "105560", "111148", "110139", "096282", "082045", "106264", "069703", "053493", "038734", "018078", "098454", "114554", "124578", "112029", "051926", "103383", "042408", "133265", "067626", "035137", "000882", "025571", "064105", "113508", "011789", "066403", "054288", "011217", "104363", "036501", "075938", "054426", "132742", "062870", "117160", "035021", "102800", "070637", "022139", "036239", "004111", "110624", "037734", "102808", "070930", "100877", "047768", "095458", "033745", "059865", "088534", "050829", "115900", "007462", "035238", "127033", "030012", "005143", "101713", "017550", "034527", "126253", "065317", "086729", "114251", "104722", "013773", "107992", "076794", "084733", "131149", "006494", "133493", "083710", "130984", "035868", "050855", "107417", "126119", "052791", "127157", "040175", "085896", "057534", "046723", "080199", "096800", "075737", "028063", "009826", "133344", "067039", "100356", "000451", "084569", "073171", "122738", "012187", "003046", "077738", "103152", "054084", "072493", "041263", "102785", "093719", "099550", "132737", "087402", "099058", "109640", "059041", "066283", "034790", "070378", "022130", "089562", "043774", "111470", "086619", "093320", "086416", "105043", "013118", "029328", "127809", "048816", "000633", "058418", "073616", "086132", "103402", "111019", "119321", "098343", "027233", "039940", "102972", "084215", "109036", "133758", "066990", "059090", "123377", "055961", "056901", "082560", "127037", "076988", "065226", "047330", "118001", "029154", "114782", "011716", "128752", "019126", "088664", "084000", "133782", "033272", "107452", "072174", "110659", "014567", "016155", "116366", "008001", "099568", "033296", "122652", "101122", "090150", "098907", "069792", "044517", "000257", "075268", "025699", "018029", "118518", "016753", "025214", "019037", "065672", "060698", "013606", "022653", "012703", "058064", "071783", "130832", "010006", "128123", "123765", "074141", "118558", "114164", "036024", "078509", "096261", "003554", "003125", "026715", "080111", "101501", "106802", "017075", "118160", "051596", "121549", "006352", "070766", "022158", "088271", "057839", "012580", "073424", "080694", "128742", "100718", "073564", "089826", "127951", "047839", "063809", "005529", "055109", "050985", "048730", "081486", "077193", "019764", "106657", "122172", "096779", "095614", "122906", "082109", "008469", "118616", "023365", "120231", "086145", "086049", "040549", "043046", "123936", "107083", "118078", "033562", "015856", "106559", "092714", "081776", "065535", "059916", "075484", "129286", "105902", "123456", "102312", "126660", "052705", "084843", "128000", "051959", "046538", "057712", "061084", "094640", "069277", "036202", "100400", "123126", "100607", "019358", "086888", "059714", "022988", "043391", "060576", "127746", "051805", "067500", "051512", "125221", "034825", "000273", "049769", "003248", "045617", "076720", "128101", "124400", "118475", "050699", "024460", "003846", "090107", "131839", "102660", "014398", "048577", "045622", "098513", "122839", "037430", "061509", "070398", "061388", "009399", "116319", "118330", "084804", "048641", "129914", "022483", "056366", "092488", "074559", "072964", "051554", "048389", "044368", "075580", "039117", "045700", "040349", "126841", "034440", "044579", "116605", "032113", "130805", "046408", "044910", "082521", "087494", "033729", "003772", "023890", "114629", "016968", "051876", "076568", "032673", "099960", "116647", "087242", "130275", "053614", "042687", "081146", "038154", "016567", "043719", "029108", "016693", "000863", "009672", "096529", "076797", "093537", "094629", "131124", "123408", "038368", "040230", "027893", "039791", "043685", "106258", "111976", "049050", "108377", "077239", "042333", "073500", "096547", "133582", "076354", "097473", "060819", "027275", "053072", "106774", "077609", "066932", "110325", "114555", "037921", "097714", "011846", "057486", "095726", "133560", "064536", "018454", "034335", "047020", "077129", "030099", "086229", "103729", "093565", "072644", "115206", "013703", "087498", "024620", "021884", "043722", "060719", "060181", "006004", "061385", "122497", "062059", "095848", "070702", "004324", "113281", "006162", "001053", "061396", "030885", "079024", "061221", "120716", "053697", "055715", "109090", "018659", "104168", "021336", "111792", "111908", "067260", "080013", "036076", "039229", "120439", "028582", "035391", "031650", "051219", "131232", "004910", "055185", "127237", "049366", "123943", "111467", "032460", "022918", "113570", "026943", "051655", "003787", "015369", "102435", "023039", "012178", "112121", "120674", "054969", "010783", "089060", "041239", "119784", "000997", "024117", "089712", "103867", "024716", "128207", "086314", "003177", "105781", "024457", "034509", "130850", "022800", "032872", "023185", "071676", "093573", "068352", "030312", "057391", "029886", "119478", "084134", "119743", "064421", "101723", "044842", "039735", "025922", "045224", "070337", "062542", "103936", "078682", "002629", "095941", "042749", "006839", "087266", "089616", "128520", "065445", "026326", "009103", "114967", "036796", "096538", "061353", "105773", "105093", "109617", "079297", "128236", "109257", "049658", "077857", "027297", "100805", "094467", "091176", "096668", "095200", "017795", "084344", "039023", "038809", "096816", "016470", "080155", "124675", "062567", "008247", "013405", "111666", "125833", "012836", "054621", "056052", "048938", "023071", "064428", "035630", "104875", "021446", "003144", "103275", "018849", "061140", "109116", "034276", "087212", "054454", "013600", "092355", "079398", "018795", "016755", "122892", "064643", "058383", "008213", "100760", "079890", "094721", "065261", "001986", "033505", "104890", "103979", "043870", "072563", "005815", "114044", "131652", "024966", "029474", "006964", "008210", "034585", "023126", "062442", "019534", "094702", "051025", "031738", "050119", "089443", "039567", "057149", "133024", "129519", "065808", "014073", "018526", "125581", "076863", "008468", "043512", "118402", "046183", "091156", "080636", "108587", "084976", "022897", "059228", "018792", "044657", "072814", "067780", "007375", "005646", "075588", "104525", "020588", "080908", "129950", "011426", "085429", "007802", "111067", "030746", "121659", "067438", "020032", "105330", "031889", "069524", "115938", "086919", "104032", "022051", "004785", "106307", "123516", "082650", "103271", "024196", "019981", "061958", "021816", "016943", "101934", "089004", "090253", "085239", "125191", "101886", "067803", "093049", "083731", "006526", "090384", "016915", "127353", "120074", "092048", "005779", "001249", "030680", "048834", "081487", "063536", "113746", "080893", "110043", "012543", "112251", "059829", "082837", "022996", "010941", "096103", "031501", "127128", "106691", "096828", "089377", "038888", "080524", "019720", "024008", "022838", "026643", "012572", "070640", "019391", "067427", "041290", "103406", "087957", "048916", "093918", "059247", "095194", "068782", "078184", "020554", "071154", "070948", "119297", "046270", "036300", "106316", "044271", "111737", "108795", "018297", "075250", "070164", "040037", "110836", "021034", "057179", "056844", "092218", "016937", "009191", "022524", "076580", "113212", "132107", "074209", "048623", "048907", "025761", "034574", "058991", "006931", "093379", "107506", "088507", "128625", "125693", "069223", "032219", "013792", "113229", "075409", "074390", "128331", "011440", "126953", "095129", "119109", "018864", "083597", "033408", "020128", "117979", "042041", "091612", "027330", "016495", "003088", "012305", "110741", "042261", "110102", "064720", "024243", "081050", "132461", "083279", "010840", "096053", "019466", "027941", "082328", "096463", "073743", "095648", "066686", "036460", "132382", "128153", "053455", "063658", "131669", "104893", "127026", "026679", "065446", "063249", "104625", "110025", "040830", "066285", "035242", "039800", "121068", "111708", "003436", "024746", "102089", "061055", "124227", "077244", "130773", "088999", "133701", "076458", "062005", "029661", "045439", "016747", "080583", "022329", "118600", "098520", "037251", "040479", "075375", "017214", "041195", "033494", "128856", "109772", "053724", "133492", "115090", "114933", "014174", "092445", "060547", "085398", "128892", "095656", "036285", "082222", "030716", "091707", "093895", "058490", "078583", "118586", "047380", "017748", "003854", "129204", "021832", "081744", "105745", "054787", "063614", "023344", "020499", "069808", "002728", "048459", "105947", "039831", "060539", "068945", "104806", "123201", "022883", "104728", "017515", "124056", "041480", "075915", "047742", "128253", "067392", "095079", "073030", "063220", "041442", "115986", "025145", "006634", "064041", "015453", "067449", "081858", "062981", "104572", "117661", "090105", "121691", "078177", "019711", "061625", "096640", "018894", "094826", "091688", "045763", "048462", "133420", "100515", "076343", "012762", "026507", "043428", "024022", "115734", "080338", "055030", "001091", "026987", "036651", "036876", "044878", "066058", "057717", "089995", "043232", "059339", "100788", "084999", "079903", "117753", "101356", "009842", "113772", "002634", "073706", "011379", "029483", "123846", "025012", "005173", "047034", "056469", "044540", "061813", "016346", "016079", "109202", "027145", "023424", "003449", "038468", "085617", "062076", "063244", "116284", "111405", "131561", "087471", "076610", "027440", "063894", "027754", "042140", "040346", "071633", "024421", "124970", "121185", "086838", "121597", "091791", "108229", "115424", "048474", "017431", "040779", "072993", "108935", "052300", "039490", "057230", "076368", "119831", "083882", "053541", "041228", "067129", "040679", "080394", "032056", "066354", "125598", "070609", "044381", "070708", "075667", "066841", "009229", "037351", "126871", "051007", "078140", "016909", "121032", "096995", "037996", "065357", "095448", "077076", "050244", "040095", "037059", "116233", "106837", "115490", "065872", "108739", "104909", "055223", "113969", "030338", "095706", "042512", "028430", "081415", "040717", "103400", "058727", "020409", "051770", "072448", "016926", "037854", "102948", "067375", "044841", "094577", "013331", "050054", "073391", "116101", "050861", "116356", "031063", "119652", "079316", "076333", "098452", "026907", "077038", "006580", "074010", "053216", "018194", "080202", "072641", "016338", "121161", "092997", "131983", "086058", "054462", "041137", "052608", "056860", "023254", "092661", "083775", "059037", "043696", "003302", "091471", "051444", "073419", "060095", "105937", "007522", "040203", "056612", "043236", "111567", "091540", "031683", "033023", "035679", "066282", "007192", "010713", "093481", "037491", "020639", "098497", "015610", "131773", "104900", "127991", "025443", "119087", "017427", "056270", "113118", "004065", "108169", "028850", "018888", "110173", "079652", "113510", "125206", "097782", "096962", "010556", "017623", "119700", "001389", "063487", "119149", "107613", "115606", "025369", "000725", "018394", "105479", "085659", "131591", "010193", "002775", "100317", "006020", "054727", "039122", "041649", "062334", "092266", "028805", "035420", "086921", "065391", "097956", "020949", "008502", "008418", "022912", "081567", "016935", "082809", "103874", "128758", "049194", "087893", "028183", "097114", "060010", "005148", "056593", "048681", "102481", "010832", "019868", "055665", "120892", "017376", "010332", "042871", "093343", "108328", "048212", "067173", "005535", "105342", "021817", "115491", "059790", "094278", "007131", "128853", "027438", "016202", "103641", "038291", "074309", "053632", "006929", "129449", "065425", "115574", "086550", "020001", "020767", "040898", "044832", "011806", "089388", "033382", "075926", "000018", "086375", "117895", "037169", "017595", "086433", "014570", "118319", "012158", "086471", "067594", "133415", "102211", "061391", "121787", "026786", "005643", "108422", "118547", "084403", "069027", "057333", "123364", "072902", "038635", "034089", "097962", "007659", "123218", "124761", "048544", "022634", "103776", "108145", "015309", "119505", "070623", "074994", "102859", "130300", "040143", "116389", "009293", "070796", "078944", "005935", "041192", "031316", "009676", "113277", "043069", "124714", "019509", "085989", "133772", "084640", "054527", "026476", "019895", "059946", "021575", "061855", "008769", "121023", "001925", "082076", "092919", "080375", "020111", "085470", "087484", "096339", "023041", "069072", "073622", "054709", "067940", "078078", "008204", "039263", "126480", "125207", "108929", "042028", "012811", "116774", "051666", "117701", "047296", "080789", "001884", "131268", "089853", "107612", "029869", "011890", "012339", "048241", "102119", "052624", "022846", "123539", "114420", "021862", "054824", "090557", "011094", "125680", "008330", "014045", "084336", "022041", "109796", "011850", "071714", "123666", "016852", "080455", "066409", "101475", "032407", "093350", "106608", "058496", "099850", "126049", "034753", "103679", "006528", "065794", "017587", "125541", "101624", "092525", "117047", "018660", "031904", "011859", "082905", "011501", "120648", "095562", "080520", "120808", "037147", "113968", "071842", "098928", "073346", "027162", "040556", "092170", "094447", "061249", "091727", "030019", "051885", "032274", "016706", "073154", "054162", "002148", "062636", "028682", "003478", "082461", "031400", "046558", "009922", "097491", "109840", "132040", "091678", "112050", "004226", "066637", "128269", "093371", "060391", "126632", "081668", "053902", "013104", "048981", "055201", "038708", "027058", "103579", "079826", "064948", "129546", "106902", "119275", "011011", "078889", "125817", "122684", "092033", "073375", "050138", "099968", "069529", "001257", "018044", "024710", "005651", "078875", "088002", "053185", "021850", "028629", "054010", "033211", "056870", "125601", "125072", "014345", "013896", "029020", "018193", "056517", "064185", "019410", "063141", "126760", "038097", "120824", "051367", "045278", "032804", "079895", "131422", "112727", "096246", "011207", "061060", "078340", "082638", "056343", "111672", "091894", "028020", "042063", "083176", "045426", "007287", "132422", "131034", "132405", "042158", "094198", "056559", "112236", "114085", "078096", "024753", "111084", "065116", "109083", "007983", "067268", "119026", "043202", "109462", "031746", "069868", "051680", "122746", "070761", "036916", "051109", "030210", "094978", "031158", "019599", "019321", "056211", "060934", "029875", "097784", "113041", "056030", "078409", "096848", "078343", "099880", "049786", "017422", "023437", "065428", "126824", "009396", "057884", "107156", "052944", "065501", "062535", "011644", "052841", "083321", "069875", "021676", "010890", "059874", "026179", "061997", "104541", "012164", "007032", "114376", "020520", "017226", "066830", "119288", "055814", "110455", "099873", "126887", "023342", "035805", "073144", "069343", "003937", "127866", "024090", "055571", "018074", "042653", "072393", "039494", "034837", "080318", "068492", "040676", "060555", "114525", "063240", "102431", "024946", "075850", "058303", "093298", "047140", "114237", "107801", "060639", "081867", "038141", "029142", "019407", "074232", "079508", "000256", "044081", "035855", "046208", "008645", "104397", "013329", "111949", "003306", "105270", "053435", "094791", "065375", "014677", "078055", "083647", "100473", "131215", "045246", "040166", "047275", "005342", "133463", "065789", "047188", "057870", "059195", "031300", "065656", "038146", "066665", "016112", "095869", "068291", "127669", "042029", "052322", "003206", "061539", "043124", "112304", "033062", "113704", "058237", "126893", "021061", "097691", "078846", "087161", "050035", "047647", "107015", "056957", "112173", "030046", "089502", "021028", "084383", "103592", "043444", "084753", "077159", "027345", "044373", "062664", "012664", "050118", "015998", "114873", "127594", "111237", "061145", "031483", "052899", "029618", "029520", "052613", "024733", "059637", "072169", "070385", "067342", "002591", "039066", "092955", "081287", "018989", "028011", "020675", "084729", "019865", "104092", "086971", "022927", "005505", "079055", "099795", "097365", "012206", "036519", "042365", "078082", "108484", "125472", "027305", "060980", "127616", "108188", "129352", "098090", "105157", "096695", "098198", "093965", "005052", "091277", "083893", "053451", "069084", "130839", "023951", "124641", "035154", "067832", "133574", "009414", "057473", "063380", "106770", "114366", "047284", "027098", "009185", "112141", "029008", "117630", "091040", "040554", "071406", "045090", "111667", "080835", "065744", "055622", "065169", "061533", "042048", "052454", "068073", "030619", "016403", "093950", "082558", "120376", "078217", "088589", "091997", "001808", "058119", "112028", "068206", "069508", "119049", "123115", "113186", "024835", "117789", "085471", "056916", "006708", "033996", "100776", "095845", "049849", "104214", "071356", "007271", "091204", "116125", "132629", "089610", "068630", "092450", "045557", "071417", "124402", "042592", "023049", "095347", "008701", "072230", "089800", "001506", "074570", "132850", "072086", "105173", "002917", "115266", "010174", "133753", "125039", "093276", "031359", "066176", "042505", "131069", "023891", "043288", "111894", "102978", "048919", "111335", "038331", "063414", "028520", "017386", "036770", "099729", "036795", "039810", "052246", "008790", "076256", "102397", "049210", "109373", "004683", "068242", "095791", "045153", "023518", "035880", "022149", "071137", "009890", "103145", "086384", "040266", "077190", "098947", "007699", "032199", "062335", "043724", "055878", "117221", "053538", "043975", "109178", "118054", "029910", "036583", "127147", "051977", "119476", "084171", "047712", "067226", "006511", "124330", "017291", "117863", "066586", "035133", "020512", "060291", "101795", "094002", "119582", "070364", "109236", "043950", "128954", "007906", "016914", "096352", "117106", "057198", "111713", "022780", "072773", "001803", "051363", "013945", "115854", "078178", "008198", "057062", "105948", "129337", "036892", "043656", "123825", "029006", "064051", "129189", "091749", "087256", "042580", "110473", "022413", "124073", "020685", "071907", "124316", "017102", "014179", "084588", "014745", "075604", "100118", "057046", "035897", "121391", "093256", "074634", "122249", "078452", "059233", "118630", "049976", "091619", "085586", "109317", "044600", "073395", "000758", "010639", "089138", "059955", "008775", "063004", "067773", "115538", "133299", "077948", "019137", "058097", "096705", "013962", "126317", "131861", "101776", "104529", "130396", "080659", "097924", "016850", "043909", "129012", "033680", "123274", "067584", "125037", "046779", "118226", "129991", "061521", "054004", "111812", "054036", "095105", "069406", "131985", "067717", "040198", "085653", "123039", "034272", "107518", "098699", "074316", "068915", "048830", "125746", "050758", "091792", "082189", "116906", "075803", "074278", "076477", "106685", "132077", "055731", "039344", "087240", "038498", "093988", "002824", "058529", "071051", "128606", "100380", "084956", "002816", "064623", "068521", "067983", "112363", "098556", "042226", "002712", "046240", "035176", "059902", "114674", "104427", "049068", "120321", "035279", "035977", "056958", "096192", "060290", "034360", "035215", "061598", "070450", "035366", "047329", "056876", "084440", "101619", "074806", "086235", "043401", "064619", "105355", "031231", "008542", "044000", "077960", "076184", "035120", "011561", "126693", "081766", "088828", "090297", "080605", "108345", "007986", "099652", "042279", "071739", "050344", "098073", "019705", "036302", "071142", "109818", "064338", "052048", "032931", "133111", "012950", "132130", "050945", "075015", "044427", "081028", "094494", "052697", "088661", "133192", "073196", "132380", "060837", "080855", "053765", "122074", "107322", "118020", "132257", "068736", "114484", "129056", "109155", "095690", "002240", "069652", "060376", "097080", "091132", "127962", "043939", "094927", "052924", "073679", "109432", "113266", "061880", "076987", "057299", "112003", "005133", "035387", "051699", "096278", "029568", "094514", "023455", "016210", "131852", "057867", "105489", "125031", "110666", "066065", "068806", "092845", "047636", "111043", "086041", "001574", "033613", "002455", "030352", "107976", "062331", "097615", "125186", "092892", "070673", "106631", "048430", "072009", "086685", "076025", "062966", "044258", "091296", "126397", "112330", "044610", "111030", "044101", "034365", "026259", "113656", "118640", "090086", "078103", "049008", "093164", "114683", "073876", "068465", "034254", "116845", "068985", "036485", "076167", "024270", "116540", "000181", "017917", "085497", "090443", "059036", "107725", "070104", "116454", "036173", "131187", "031544", "109540", "012720", "090896", "053443", "054396", "002283", "103843", "133093", "061791", "090908", "129228", "027770", "079329", "047163", "125774", "016978", "048240", "100836", "130146", "093693", "057031", "110732", "037703", "028887", "012006", "010895", "110805", "026738", "086553", "033283", "093928", "025316", "115145", "124437", "060592", "126975", "001124", "033066", "022142", "127996", "115067", "079752", "055885", "100740", "081578", "125728", "107251", "060889", "094672", "046245", "121640", "037120", "052813", "132080", "047660", "032754", "048095", "050783", "066991", "102182", "079376", "076932", "011624", "028743", "104578", "119589", "033974", "067125", "098334", "109435", "021633", "084578", "085502", "039912", "091449", "020171", "130381", "091504", "003808", "130366", "025624", "060081", "110441", "035687", "083104", "094992", "113662", "015243", "071447", "012982", "072061", "086203", "089894", "118827", "012497", "117775", "096642", "027702", "058879", "008735", "079377", "050015", "122527", "063512", "031934", "077131", "012511", "109582", "123289", "041615", "007779", "015507", "058908", "107977", "040883", "049251", "111900", "122974", "059673", "113224", "088178", "102940", "017012", "024458", "103524", "067248", "027131", "085728", "124022", "007482", "037333", "029222", "116353", "012939", "084922", "034088", "029762", "048839", "017205", "090624", "069197", "009448", "004666", "010269", "061717", "102722", "028042", "022555", "129812", "060985", "009863", "092907", "055479", "118383", "122584", "022725", "057467", "058001", "073073", "074499", "086879", "005178", "112006", "076926", "115225", "109442", "124802", "097179", "113013", "046593", "006906", "129549", "031446", "067236", "014697", "007139", "005771", "076535", "000809", "119940", "084676", "062161", "000919", "058768", "026450", "084820", "132047", "128798", "060667", "014013", "021807", "105586", "023877", "060471", "056595", "103337", "111698", "044274", "044050", "078153", "029540", "004751", "076945", "074534", "077752", "088784", "037846", "125734", "070074", "063918", "125938", "120220", "125898", "024332", "011633", "065368", "114195", "079672", "001676", "033344", "051026", "032821", "014255", "012142", "080943", "078094", "101600", "024392", "089670", "103968", "107991", "052746", "040882", "088310", "000865", "068278", "103890", "028502", "064658", "026257", "092873", "070789", "057153", "046466", "133043", "027430", "120923", "074579", "063703", "027853", "094122", "034921", "101610", "044641", "029038", "045503", "025507", "028393", "053128", "078175", "038746", "090766", "061074", "064464", "113614", "056883", "075333", "131880", "020968", "051577", "063963", "100615", "062979", "012626", "103889", "064229", "051777", "077845", "102102", "060243", "126448", "071322", "079106", "065578", "074624", "104857", "077524", "047782", "108740", "109228", "087505", "016867", "111272", "117911", "037112", "121835", "001417", "019050", "071423", "104141", "113665", "034416", "057809", "127664", "100507", "015563", "035982", "078847", "103851", "012032", "013757", "043294", "051289", "112535", "003492", "060218", "114909", "092221", "048520", "065256", "003048", "025488", "093865", "051515", "048166", "127827", "004431", "092211", "060704", "081044", "019719", "129554", "129099", "018048", "046121", "079920", "107300", "005516", "090275", "046343", "075751", "028209", "056012", "114260", "115390", "000996", "069186", "081364", "100813", "012104", "070603", "036908", "085299", "101467", "036051", "011373", "025098", "097753", "076218", "006761", "057433", "052711", "111620", "106314", "022934", "116730", "034536", "077184", "036668", "094982", "009995", "088982", "087541", "016036", "075788", "067271", "084264", "067575", "024435", "019902", "090404", "076269", "070844", "044530", "095167", "062154", "098456", "132256", "012400", "079584", "026813", "080581", "084731", "113803", "092232", "083055", "128036", "003104", "043184", "084997", "098414", "020091", "102951", "080217", "070176", "096377", "093539", "126273", "108815", "014804", "016189", "025575", "097350", "098718", "019891", "057635", "016904", "100143", "102400", "038605", "059642", "074929", "016888", "106098", "120921", "042997", "015273", "074138", "010305", "056893", "080599", "116440", "058326", "019144", "117112", "120798", "060812", "061949", "056874", "099017", "018531", "099228", "029102", "058857", "108448", "016664", "027914", "039010", "000901", "102804", "082772", "109719", "081649", "040357", "085218", "028127", "019741", "062627", "072439", "061050", "132199", "039064", "108393", "050408", "084388", "036009", "074194", "040282", "059110", "035466", "118133", "037655", "077445", "019531", "041757", "015107", "054757", "071557", "000116", "089828", "027971", "056539", "132612", "114917", "043318", "080657", "009364", "059728", "066359", "123697", "106340", "073008", "120339", "104335", "000056", "088943", "003850", "044757", "056388", "043802", "029215", "049897", "067107", "071828", "034071", "006529", "132530", "024991", "067179", "087206", "026065", "011363", "107577", "089211", "036151", "044752", "048600", "109048", "107917", "103704", "026355", "057583", "028361", "123834", "044716", "068146", "125493", "019803", "117132", "071255", "128655", "095543", "012283", "093857", "117722", "073577", "051534", "053339", "091058", "109988", "084865", "043636", "024102", "127620", "051598", "112219", "118397", "031899", "009372", "050260", "029305", "085737", "105694", "097373", "096821", "010735", "072808", "121157", "018884", "119879", "030893", "023654", "078867", "025205", "024085", "102856", "004196", "052232", "096036", "129281", "040234", "074199", "013428", "104957", "118901", "105312", "109281", "089686", "101740", "011371", "118335", "108236", "023225", "026030", "015903", "089292", "098047", "013868", "042089", "090155", "106865", "029715", "085087", "080194", "121966", "115398", "092442", "112534", "075348", "018963", "018178", "120904", "121149", "100135", "068076", "041506", "088454", "005534", "013375", "047447", "027154", "106124", "029844", "091876", "033904", "010155", "054282", "050198", "034344", "127493", "095416", "045965", "106629", "006147", "098188", "014411", "036868", "081593", "104375", "065173", "041794", "128628", "040889", "058577", "112921", "053946", "128485", "000695", "073335", "028189", "059112", "109020", "010526", "059498", "129367", "053936", "124954", "061241", "058510", "026634", "096669", "018262", "056558", "061349", "044805", "065631", "027661", "084872", "061260", "018711", "028043", "126251", "085700", "070507", "038168", "075930", "051427", "030839", "132487", "067090", "041206", "030646", "103564", "017870", "097943", "088639", "122307", "024755", "024686", "090187", "084049", "133214", "130994", "100232", "057330", "028988", "119022", "121507", "030381", "074621", "015689", "126052", "087079", "057913", "077416", "093356", "012713", "018244", "005042", "036628", "067044", "022032", "070411", "122752", "101792", "129481", "107770", "116414", "085650", "119836", "027002", "039913", "079335", "059153", "131614", "054878", "043342", "057544", "025473", "079312", "084873", "063662", "032619", "094920", "044406", "119305", "014909", "000336", "071152", "116894", "082298", "012360", "027352", "057248", "064871", "048883", "132645", "082486", "000449", "015634", "019421", "100887", "041508", "038179", "057585", "119808", "132974", "052880", "122248", "029101", "002862", "070886", "054923", "044434", "089837", "103317", "046831", "111543", "062193", "123712", "062483", "035312", "101699", "121142", "008485", "047888", "007484", "030492", "052515", "092709", "130869", "028217", "114673", "094639", "062735", "102450", "096128", "012522", "070225", "037794", "133789", "032158", "037432", "073601", "117703", "072852", "080443", "085455", "129569", "064249", "031886", "043738", "086279", "013359", "104818", "006182", "084201", "056803", "069748", "109441", "080755", "038185", "087761", "084557", "060002", "061638", "033415", "075371", "000696", "105642", "098660", "107738", "112938", "016760", "075378", "002140", "052839", "083456", "105393", "083073", "121292", "066266", "047929", "093555", "085224", "088308", "101572", "030952", "108181", "107302", "017858", "040216", "024416", "126174", "066791", "051447", "133771", "109378", "129323", "112002", "015746", "010845", "094326", "094305", "054576", "006355", "048534", "037368", "119198", "015235", "047542", "099631", "117631", "087111", "047638", "047847", "054231", "101306", "129118", "109993", "044733", "089556", "129781", "043916", "047102", "070672", "087218", "055358", "026373", "020129", "013228", "073913", "067120", "106244", "008976", "060460", "011409", "080278", "001370", "006661", "085978", "052327", "004886", "113590", "057957", "067784", "128936", "054652", "025844", "047170", "090379", "021950", "104782", "032203", "082949", "022882", "039976", "102156", "081473", "001521", "075507", "028972", "125564", "048647", "111552", "076746", "085932", "131024", "087213", "070010", "086692", "048700", "029226", "080558", "097103", "030454", "119023", "057422", "003476", "069487", "023394", "061393", "108224", "084169", "127119", "096162", "043113", "120465", "097450", "072510", "079654", "093973", "051096", "105311", "130315", "110101", "128720", "047513", "010519", "130089", "084594", "076959", "129307", "042171", "118537", "084448", "020766", "115046", "013075", "052884", "023727", "008103", "070599", "117872", "031033", "124228", "030744", "001134", "005456", "043084", "072054", "004618", "132658", "060683", "061569", "061370", "102766", "045201", "094853", "010851", "125794", "047053", "093853", "114599", "032843", "067464", "079198", "117784", "019433", "017968", "090448", "036476", "064951", "087042", "048980", "021954", "059049", "127792", "131715", "043597", "123652", "016188", "132607", "100355", "118629", "007655", "043570", "007769", "126219", "032187", "109303", "100967", "017163", "059783", "075283", "057256", "021444", "082217", "103732", "067488", "012746", "043931", "052545", "027916", "022238", "132252", "014260", "029565", "097490", "033816", "094432", "000230", "074784", "067139", "007956", "120085", "017503", "104968", "085030", "067669", "006328", "081032", "050545", "053391", "073521", "008615", "128950", "084630", "114464", "120762", "091844", "063765", "020532", "024366", "090050", "087125", "045356", "002360", "090420", "112316", "040261", "109217", "049753", "002769", "080563", "085265", "107474", "064696", "003357", "058918", "019626", "081738", "120877", "015630", "022071", "002273", "014414", "058216", "019710", "028283", "001881", "047055", "118858", "048620", "101468", "120475", "085699", "062643", "026463", "132113", "003135", "125182", "015140", "100477", "094541", "009013", "055547", "067101", "020304", "010159", "011621", "078781", "019335", "091760", "025323", "082306", "131260", "084916", "002120", "062035", "128794", "091630", "121396", "122228", "043970", "116600", "029816", "103593", "041253", "123205", "020408", "002495", "059215", "084088", "041847", "068213", "049579", "132258", "067753", "124343", "048011", "033321", "066547", "005202", "000620", "089538", "013900", "079200", "034589", "056188", "109778", "132063", "079455", "063079", "033319", "120005", "018073", "059726", "108297", "084203", "072774", "008203", "111280", "065929", "010557", "085354", "069355", "042609", "078526", "032277", "074881", "059381", "071625", "111849", "043136", "034005", "092917", "065276", "024200", "075490", "130165", "003715", "102084", "097341", "022818", "032311", "067728", "093872", "091153", "121414", "039575", "034010", "114447", "133479", "075569", "040928", "002434", "060125", "097563", "112794", "116146", "082523", "024952", "042296", "089530", "096584", "079995", "132373", "097796", "054186", "094806", "128355", "017736", "032226", "022026", "052780", "121080", "103376", "096670", "004459", "112190", "064313", "092914", "116931", "025077", "013124", "058176", "083036", "002830", "024615", "115757", "001603", "002952", "042010", "058050", "099539", "123136", "119472", "008687", "047083", "089740", "036671", "112473", "126346", "074268", "021872", "000623", "084921", "029581", "069847", "085351", "130487", "124750", "080513", "067381", "119585", "049288", "054730", "051549", "051120", "028827", "133341", "133626", "120997", "115097", "075112", "061704", "087445", "123407", "015754", "020239", "088421", "050897", "109118", "129705", "091957", "063874", "075619", "027383", "040032", "060406", "126797", "031664", "104137", "092347", "131733", "023801", "099378", "111516", "011987", "119431", "038620", "029086", "062957", "032115", "043441", "085850", "098701", "032044", "041076", "105472", "088138", "133489", "127567", "087680", "069230", "106067", "043859", "127207", "068872", "008639", "044877", "112017", "114706", "072508", "090306", "088339", "034359", "086622", "014392", "091893", "069282", "056381", "034161", "027861", "036545", "004781", "049300", "070011", "062817", "102773", "119704", "119837", "114313", "024175", "101835", "047952", "042127", "030123", "133257", "126150", "124111", "004342", "070455", "002733", "035482", "088698", "011341", "069635", "041404", "016542", "033511", "019906", "020331", "131104", "120022", "099287", "026193", "005092", "115272", "132574", "087013", "115367", "118374", "007393", "067266", "115289", "019880", "006315", "049536", "003914", "113406", "076511", "040564", "021498", "074240", "084110", "111848", "036422", "028094", "009591", "112566", "061693", "072388", "067972", "027521", "071827", "125137", "066186", "111132", "042011", "042349", "044475", "028041", "114840", "125825", "020591", "020381", "047320", "009882", "066039", "058492", "023495", "046546", "095875", "047545", "012710", "023110", "005580", "003463", "008747", "041085", "018723", "112846", "008433", "058457", "033762", "088393", "122799", "127145", "131218", "131111", "042016", "108667", "081181", "084669", "048867", "026363", "054060", "067521", "130348", "082836", "107027", "059998", "028510", "019529", "059332", "064849", "007128", "061648", "104178", "049560", "107509", "023386", "129425", "017366", "015157", "107152", "069046", "009909", "115193", "066223", "096470", "132236", "112864", "048321", "091326", "112281", "082700", "026872", "092338", "122939", "064180", "128582", "074442", "014059", "020922", "131897", "005849", "033678", "099118", "063952", "064999", "092141", "110775", "056339", "018846", "035384", "127041", "012790", "074919", "024847", "021887", "010969", "055468", "041562", "022582", "113343", "114512", "029987", "053406", "061133", "080826", "084290", "001086", "066437", "027160", "114663", "105406", "086966", "038548", "058599", "100347", "021103", "052794", "033605", "025164", "114725", "062178", "026949", "059811", "068652", "003710", "129443", "031809", "095525", "094296", "128921", "038722", "075038", "082852", "051001", "020719", "097430", "115704", "038155", "001698", "075591", "131790", "071784", "004150", "078133", "038075", "088450", "119093", "127275", "056001", "105365", "087397", "034824", "085456", "037985", "007767", "089087", "012977", "003900", "009528", "016817", "127994", "073377", "015250", "024803", "030184", "068778", "099270", "088128", "039824", "042690", "045407", "040816", "008869", "044387", "014616", "053195", "036793", "053245", "086462", "031281", "080359", "116462", "037835", "041193", "056824", "077080", "017255", "064108", "115964", "073669", "087972", "060193", "128016", "047487", "029914", "074560", "089263", "108474", "061804", "019587", "079905", "002935", "045241", "020798", "120802", "075024", "049056", "070578", "034970", "011960", "115936", "038922", "111468", "084902", "003189", "046430", "082079", "023645", "082453", "130889", "037031", "049218", "073865", "010177", "057753", "097156", "046049", "039684", "080918", "006691", "105160", "086043", "119939", "023887", "046403", "117984", "040566", "046638", "044687", "014076", "039071", "126469", "014911", "106407", "105229", "098783", "029505", "097242", "018522", "047271", "017510", "036100", "036478", "003540", "033437", "005544", "065191", "129871", "129930", "064839", "023433", "096122", "036105", "044134", "125122", "107299", "055456", "060430", "058821", "039585", "058025", "066384", "002698", "111979", "054319", "067043", "107362", "001514", "050106", "101716", "062663", "116318", "111490", "017390", "079888", "089592", "039395", "009857", "026886", "042344", "099483", "007048", "078778", "001175", "045455", "127933", "058982", "008430", "113271", "068844", "073761", "030252", "006500", "086397", "104647", "078938", "077959", "083632", "007499", "133110", "020143", "039550", "059821", "010683", "092551", "116138", "118859", "071540", "043270", "104835", "077381", "076140", "001385", "102578", "094820", "118774", "056807", "075334", "093071", "047607", "057405", "038812", "039844", "015721", "126978", "012819", "035142", "019384", "045592", "004868", "108041", "037376", "084806", "092755", "010074", "013386", "036045", "078555", "083204", "049713", "032493", "064699", "043311", "106175", "065300", "052179", "051689", "093695", "095346", "099669", "131351", "087472", "077079", "115830", "016451", "067247", "123065", "027755", "093399", "045405", "055004", "091384", "069043", "053427", "006601", "094250", "109625", "054474", "079327", "000939", "071797", "028676", "042979", "123725", "049464", "010842", "112899", "041277", "009895", "048646", "100715", "125328", "102713", "113719", "053110", "128982", "020843", "128459", "024358", "036841", "032622", "080238", "024043", "000590", "057305", "008604", "063661", "111453", "129215", "106932", "008773", "020418", "044920", "043728", "028402", "074299", "029991", "111930", "112724", "074341", "051305", "080071", "058507", "095418", "121697", "131856", "011638", "069482", "076443", "005707", "120558", "006851", "066088", "037129", "005449", "066844", "102484", "116802", "123426", "086933", "072208", "129351", "092306", "000466", "130892", "010363", "130862", "108874", "132582", "040397", "067057", "071628", "116631", "119053", "098339", "036527", "096247", "130797", "021930", "013135", "115385", "009121", "051586", "070322", "099687", "041160", "019020", "126392", "061479", "081519", "098021", "036550", "028607", "125754", "046725", "028302", "092294", "096666", "032125", "020333", "056735", "030305", "055980", "113479", "083492", "054196", "031564", "111251", "131553", "048497", "010738", "061846", "106739", "129064", "012379", "112771", "060171", "029814", "082643", "127247", "077302", "102029", "024732", "067701", "074402", "099040", "071753", "064257", "032922", "110710", "065028", "022529", "026488", "044078", "102528", "079848", "114859", "068674", "100984", "055833", "011050", "100734", "039200", "057781", "112783", "058131", "037015", "087501", "125157", "012027", "019792", "044425", "087249", "055674", "104171", "125197", "042947", "119764", "066862", "070670", "080805", "012014", "010044", "130276", "011231", "020638", "030386", "043902", "063799", "065087", "006366", "010604", "095954", "086741", "093968", "118164", "131370", "108123", "054734", "047411", "116737", "121773", "015646", "099317", "122028", "023380", "115352", "014512", "112813", "052497", "091350", "091655", "130678", "083884", "044712", "007800", "004604", "068716", "084424", "045864", "120117", "017299", "063665", "002012", "078225", "103139", "015490", "104871", "117399", "109597", "062453", "079222", "055667", "018820", "034817", "014963", "034456", "100532", "028906", "113432", "057709", "024501", "116232", "001043", "103952", "083079", "048841", "012500", "076363", "011015", "005634", "038148", "124892", "125920", "092502", "132711", "073240", "054015", "001885", "031243", "035952", "064746", "080833", "083237", "068221", "066769", "016379", "057947", "123015", "056316", "106220", "037677", "036746", "075498", "063897", "085544", "074440", "063013", "119323", "118543", "128290", "021334", "040312", "077641", "077585", "094013", "126527", "122419", "047654", "087437", "045891", "132552", "063075", "053215", "046190", "104099", "079074", "049962", "114369", "055911", "050537", "114141", "035963", "090222", "126877", "006467", "124059", "029768", "064075", "023766", "002482", "132760", "020808", "100366", "003448", "104105", "104783", "066005", "049537", "030718", "118486", "033627", "090784", "019396", "067689", "030593", "098949", "112306", "046607", "045858", "129121", "086663", "080868", "073262", "117892", "018349", "121085", "044617", "067000", "102542", "128074", "108600", "076407", "043117", "096689", "107816", "008805", "121021", "060678", "058416", "132944", "107963", "116606", "037353", "116873", "076852", "028939", "017607", "057613", "130426", "054747", "035227", "024522", "103340", "123433", "000500", "092245", "066418", "112887", "078641", "124606", "131396", "053819", "046177", "043800", "065197", "065763", "036494", "122325", "115516", "049474", "051999", "029010", "011513", "036066", "103802", "063568", "009618", "027290", "010281", "024121", "092936", "089975", "025984", "121223", "097432", "015750", "029887", "002863", "068824", "110764", "031841", "004606", "086715", "070278", "114031", "074770", "079705", "017760", "061139", "097241", "049895", "068200", "127284", "026936", "029206", "022515", "124202", "014679", "104142", "050673", "111707", "084126", "078680", "070028", "107404", "090350", "027510", "097183", "007589", "049542", "110895", "005060", "026499", "035724", "008835", "089023", "028270", "085783", "084165", "130023", "035079", "011455", "007276", "026351", "070204", "114940", "010101", "120887", "090489", "042834", "083813", "069605", "107922", "049819", "057282", "054760", "030573", "097918", "034019", "110517", "086393", "109865", "078062", "075562", "025741", "027713", "074246", "089274", "022431", "104259", "127846", "041639", "076577", "104457", "057160", "038989", "100968", "049587", "010820", "067492", "023279", "093265", "081318", "111142", "059614", "112705", "088879", "112739", "126320", "013590", "123932", "097721", "089054", "095380", "036032", "023994", "113794", "028423", "073185", "110350", "117273", "087123", "113544", "046448", "076290", "114789", "052796", "034508", "000228", "122484", "095073", "119796", "130974", "096912", "085689", "133732", "045507", "016505", "110990", "043901", "097095", "042987", "035554", "098204", "002565", "040831", "014095", "000849", "067612", "034515", "041924", "127133", "083975", "082105", "124573", "077148", "043508", "056676", "033364", "130334", "041463", "076805", "044852", "089264", "120307", "064889", "111771", "023119", "033255", "059005", "072892", "027243", "010618", "080931", "121509", "025589", "030585", "031423", "058798", "099300", "103036", "090520", "066961", "039741", "121135", "016156", "015471", "026817", "046954", "105047", "039709", "103715", "034605", "081494", "008324", "111527", "118994", "041500", "027530", "099627", "093338", "017561", "115313", "046288", "008935", "031753", "092467", "133216", "053845", "080059", "075793", "035440", "013901", "077447", "131323", "082229", "068334", "033254", "060691", "095516", "039799", "062196", "020791", "019040", "012537", "133602", "046463", "048670", "000169", "063562", "107671", "107578", "104925", "069661", "046038", "016418", "045589", "028795", "118362", "106270", "059556", "093476", "031765", "124036", "035780", "034433", "056763", "130353", "039482", "082913", "117269", "082928", "008473", "124310", "029650", "107970", "059348", "051116", "025899", "126958", "128482", "046402", "063053", "082418", "032694", "109383", "119571", "078719", "122114", "087747", "105622", "130964", "032351", "086764", "071043", "117760", "083858", "091821", "119460", "128604", "084068", "059896", "122612", "070976", "092916", "112169", "120767", "083541", "061712", "039457", "009770", "044879", "073819", "104172", "023590", "103885", "076803", "005591", "054092", "061270", "057017", "084559", "009596", "006099", "034603", "067528", "021155", "019849", "043681", "111469", "034187", "013357", "053567", "074143", "029181", "065237", "058162", "092896", "125500", "072432", "108559", "101085", "018592", "101127", "113531", "047036", "012969", "104475", "103946", "106324", "054750", "017732", "026511", "065417", "015592", "033216", "119120", "028132", "020324", "093552", "125269", "101497", "030382", "020165", "129079", "078754", "060223", "067404", "029721", "031494", "054921", "048706", "117219", "057553", "000025", "113978", "115306", "014147", "062705", "068012", "029627", "067189", "017160", "042586", "094765", "091492", "092147", "062899", "079326", "009383", "080612", "007819", "004030", "031797", "004057", "077681", "107466", "091784", "001331", "082927", "072136", "007833", "056764", "065338", "074298", "002703", "001421", "099832", "051632", "122923", "090317", "050332", "023128", "047550", "018287", "047204", "044624", "083960", "133219", "107002", "027639", "018725", "092313", "006663", "017078", "023191", "056759", "111576", "111170", "065469", "101965", "114739", "040733", "025201", "001626", "039039", "054978", "131632", "098745", "132641", "000376", "070044", "023302", "054093", "055579", "099672", "110982", "030688", "030270", "003438", "009063", "057033", "072456", "022202", "048030", "125294", "063361", "092662", "021502", "128946", "026844", "055408", "023354", "095277", "072476", "036139", "105295", "125796", "042450", "085893", "095126", "035807", "058528", "116007", "026198", "047833", "035925", "006718", "092701", "000348", "041720", "056109", "063514", "053843", "035781", "055396", "044708", "056386", "000203", "002345", "071955", "046377", "039012", "110850", "132292", "112830", "099392", "104405", "082156", "082468", "110492", "114956", "006674", "013947", "116903", "075187", "028996", "046071", "042293", "080387", "019502", "029526", "094935", "054596", "016883", "113854", "023087", "047520", "006637", "087923", "094800", "126778", "015692", "131239", "022917", "121962", "056940", "011901", "010090", "124108", "032508", "122090", "132354", "031876", "072442", "087060", "043071", "074102", "064812", "032282", "108483", "087994", "048369", "005117", "057796", "076875", "059746", "077926", "003545", "107398", "044935", "016655", "086860", "131371", "023023", "095716", "024666", "091513", "045252", "016529", "081196", "126905", "097075", "093515", "067819", "054959", "026298", "029529", "031091", "052287", "041626", "069081", "104210", "055632", "027600", "036464", "112795", "131054", "127401", "028082", "030079", "097984", "064187", "034120", "029287", "007439", "081188", "096768", "010406", "051684", "039374", "119440", "077106", "070263", "130902", "100423", "058170", "071227", "057200", "087551", "069711", "043107", "083664", "017416", "038406", "122669", "024944", "111750", "049932", "120110", "088860", "107719", "130091", "011647", "066317", "005552", "103973", "063275", "083460", "008728", "126848", "054776", "040394", "064559", "011202", "039154", "131081", "109725", "013273", "063219", "080066", "019260", "057317", "107697", "015822", "083976", "063890", "057936", "014776", "050438", "059871", "089062", "130504", "108370", "029484", "003524", "081688", "023555", "036207", "092150", "023761", "129793", "113078", "053434", "032744", "014214", "042778", "068312", "015569", "017984", "025183", "058169", "093856", "115785", "066888", "023035", "087405", "073042", "102051", "113548", "116240", "019951", "005488", "024908", "114848", "058178", "079358", "062867", "041023", "031144", "006673", "083028", "074521", "010489", "006309", "033021", "131498", "121699", "067822", "124911", "060307", "108813", "003127", "072467", "068886", "109058", "128227", "029198", "049248", "020645", "015447", "117011", "043815", "108133", "011888", "122926", "129967", "025452", "132011", "094896", "038142", "060083", "056429", "123288", "107811", "115478", "085985", "020241", "100775", "090332", "051435", "062564", "122297", "028226", "078896", "124505", "084870", "091385", "065832", "092792", "015285", "066745", "042563", "034125", "056227", "052114", "065679", "042647", "118094", "127670", "019802", "093572", "092153", "102406", "127561", "016322", "062280", "117397", "004138", "028742", "036463", "025259", "034834", "132528", "058771", "001681", "082794", "097588", "076259", "008721", "081895", "053916", "115309", "107930", "069712", "070392", "080587", "072090", "117578", "110871", "022282", "101394", "063690", "101851", "034063", "077588", "013824", "096548", "104653", "057288", "105105", "010824", "041110", "012929", "044043", "013115", "011914", "014486", "013594", "105436", "132128", "121746", "015743", "049589", "019099", "078357", "105293", "088115", "012554", "093144", "051588", "121511", "098945", "040002", "087571", "083323", "098899", "017142", "012747", "029069", "089287", "008606", "024937", "126364", "131748", "057125", "120942", "007752", "069133", "088742", "102680", "120546", "092343", "082901", "039235", "020516", "099666", "054672", "097910", "036902", "096089", "044675", "016152", "090153", "037730", "081988", "058148", "072019", "072227", "082965", "124786", "072803", "118775", "128234", "075443", "068961", "130716", "070915", "133715", "060991", "029896", "119670", "016275", "123197", "079837", "130026", "047298", "066624", "104435", "070689", "074942", "109231", "055724", "010258", "125434", "083284", "076204", "030779", "122656", "030609", "129115", "012899", "132357", "012081", "006024", "039075", "095874", "132097", "078146", "052155", "080573", "111960", "069440", "044593", "088772", "019386", "130210", "006734", "011391", "096984", "128599", "037154", "080538", "079587", "076505", "083713", "105543", "049448", "046502", "029025", "122548", "075228", "103309", "121058", "008866", "021604", "105198", "063072", "107483", "027188", "036616", "078494", "092018", "115877", "086601", "002016", "102451", "037536", "088492", "012030", "110068", "070046", "001537", "101240", "084480", "113955", "000735", "071093", "132037", "070634", "010051", "114139", "075576", "073870", "098725", "119129", "097067", "016422", "111931", "022030", "117246", "040150", "093315", "074338", "128786", "115106", "069579", "005495", "002826", "002102", "103733", "088619", "087357", "013630", "025664", "123242", "124058", "058901", "064974", "026354", "111693", "040591", "021692", "077490", "112757", "113367", "107206", "008336", "011233", "026966", "058826", "074347", "000563", "089172", "125237", "071030", "103148", "065260", "071549", "059024", "022811", "119966", "021010", "054442", "012325", "020825", "092348", "039679", "114183", "033821", "118581", "077014", "010640", "104864", "065156", "051642", "030837", "013439", "014832", "084512", "126751", "107213", "117235", "074766", "070648", "121739", "022944", "069664", "113667", "079136", "106674", "107692", "077165", "055599", "099102", "070817", "107045", "095602", "129637", "071451", "090982", "125691", "083191", "129516", "046528", "032166", "007354", "122323", "001061", "067229", "125499", "018413", "054819", "091187", "116667", "015214", "120537", "130636", "033206", "058256", "094101", "101966", "055550", "050661", "028325", "040218", "072296", "042312", "047788", "115263", "093354", "016720", "088463", "031704", "008762", "029952", "001593", "122561", "042879", "080887", "097842", "001170", "103419", "128161", "068772", "100659", "062914", "024330", "028763", "068565", "018237", "071505", "060870", "008119", "126612", "062242", "016331", "106543", "037850", "121403", "118546", "073688", "131395", "131874", "057970", "037958", "108174", "090391", "038785", "099953", "062384", "021929", "087154", "003014", "046334", "089839", "001379", "045701", "111841", "016304", "093295", "125850", "036840", "030707", "030628", "084091", "043798", "065292", "003010", "113741", "064220", "038035", "105985", "107076", "056849", "124945", "058998", "000271", "029939", "013370", "129459", "003364", "132501", "130905", "077772", "012135", "011005", "073287", "075587", "018502", "133010", "002997", "090550", "088362", "082482", "073049", "124160", "028949", "045136", "057339", "075110", "133326", "099676", "081842", "089621", "011505", "047659", "030124", "132821", "027703", "091775", "004900", "127430", "030896", "124791", "073036", "011300", "087810", "103981", "103268", "008303", "004438", "129181", "054487", "121311", "061319", "075743", "053986", "049024", "025029", "130039", "104311", "090883", "066877", "062707", "104962", "041916", "116891", "011192", "051570", "103154", "111692", "101841", "132981", "090869", "072987", "120827", "065792", "037937", "111118", "096349", "066505", "029782", "004983", "039967", "067431", "117727", "004390", "024764", "057233", "110069", "101644", "124516", "093800", "047693", "099709", "040943", "000174", "091018", "072244", "035849", "101502", "076664", "033936", "009167", "080980", "048235", "086751", "088608", "103282", "098471", "106120", "047943", "007379", "057948", "071160", "132837", "026370", "023076", "130084", "113259", "034438", "015377", "068441", "052080", "029842", "049051", "015370", "026964", "067752", "060925", "011864", "077811", "031940", "017443", "044688", "015944", "010024", "112702", "070705", "089451", "042752", "124113", "013412", "043519", "038871", "097833", "002223", "124840", "052975", "088046", "065171", "092032", "003643", "035678", "054318", "058515", "089645", "039880", "023322", "047858", "117744", "073663", "114402", "116311", "013027", "026111", "005652", "066347", "008437", "077767", "064247", "003238", "000591", "084639", "065378", "123193", "095121", "041377", "033747", "014696", "064176", "096459", "032542", "047719", "016547", "088471", "038209", "074361", "055083", "055917", "118646", "080109", "050523", "035983", "050679", "006491", "077173", "005820", "036569", "023927", "106790", "125683", "001401", "020534", "011497", "038517", "069825", "038555", "077039", "014556", "109708", "027550", "115489", "013454", "029879", "100530", "025544", "070362", "109593", "028859", "020358", "124984", "012174", "071589", "052874", "133627", "051009", "038238", "037998", "124424", "017709", "109474", "089463", "067023", "065558", "077992", "119106", "116439", "040289", "091457", "063007", "070107", "062974", "023024", "091011", "075013", "007174", "031714", "084857", "124543", "107123", "098405", "039854", "079596", "002974", "095038", "081450", "111309", "059977", "032249", "086403", "098205", "082515", "122627", "076838", "052569", "084204", "124497", "093802", "049756", "050817", "005077", "037932", "081824", "099158", "128562", "040043", "070036", "079368", "052928", "087939", "118258", "119037", "030233", "083958", "077238", "083547", "046277", "124922", "128983", "128656", "099896", "108536", "100210", "071677", "078033", "051132", "113657", "120843", "090914", "070636", "066367", "062137", "116834", "096836", "102366", "061551", "078638", "125530", "055530", "047289", "069354", "035816", "122807", "109730", "025116", "102133", "031304", "058185", "019294", "028044", "015248", "075689", "129013", "103640", "021315", "112513", "116554", "061331", "035198", "088284", "131718", "117988", "019797", "071210", "093823", "032131", "133685", "008742", "124000", "120695", "033656", "031207", "065914", "015480", "046089", "029960", "011968", "006186", "052879", "038138", "028029", "065183", "057606", "057719", "066831", "000006", "117721", "078790", "054268", "131376", "097150", "115883", "080052", "087052", "110365", "032976", "116604", "063259", "121048", "011600", "062020", "031952", "084295", "015069", "041898", "133377", "063687", "121183", "133140", "001256", "083969", "023468", "052784", "026222", "108395", "103306", "122191", "018249", "059820", "028621", "107462", "010503", "011335", "070700", "018206", "046644", "039785", "052596", "029308", "105074", "018558", "097883", "130907", "036190", "021396", "055560", "068931", "098643", "014563", "117896", "116716", "021987", "070045", "099121", "033280", "039601", "067191", "002001", "114316", "047634", "024138", "095400", "112468", "071573", "034523", "107839", "103250", "059848", "058596", "026089", "102620", "101746", "091246", "069377", "017301", "022214", "093224", "078128", "112356", "113519", "017171", "035458", "075211", "079417", "118684", "034118", "056087", "070909", "046149", "067133", "110967", "111293", "049217", "045606", "119910", "075814", "058472", "061536", "047199", "087777", "070812", "057932", "028938", "095535", "117207", "114160", "093050", "085752", "017952", "068011", "062895", "120042", "054628", "077332", "052665", "130745", "048779", "084673", "115613", "130222", "119599", "098603", "072055", "074724", "063021", "042410", "088665", "063782", "027895", "084275", "077901", "039832", "072954", "120100", "095407", "045035", "074641", "014672", "068339", "014801", "099122", "015795", "130766", "064896", "027225", "131822", "106425", "076071", "070991", "119235", "063235", "093912", "094399", "103852", "043334", "077852", "097867", "023487", "091987", "124592", "042148", "128594", "045535", "025126", "110665", "041254", "076901", "033431", "073334", "017134", "002831", "007562", "058661", "022443", "001011", "106579", "047433", "084874", "061500", "018811", "014809", "030242", "095608", "029196", "097651", "075848", "061847", "084949", "039360", "073104", "061718", "117278", "037806", "103616", "066355", "038283", "059017", "093721", "109387", "085496", "045296", "091920", "045747", "045720", "031834", "023212", "043217", "018063", "007475", "116116", "071495", "110569", "088606", "096551", "116072", "026040", "132059", "093916", "054221", "029490", "026082", "056346", "096916", "042582", "102565", "004364", "058501", "032961", "095641", "097193", "089454", "082159", "018267", "097059", "016256", "080949", "049295", "112067", "102425", "040185", "132050", "086059", "042886", "046773", "112766", "042216", "034942", "052071", "119680", "088353", "023026", "012954", "016590", "077792", "122970", "017618", "112550", "041592", "047990", "122056", "111767", "030162", "008559", "121093", "028834", "042351", "128762", "008415", "013448", "072926", "047969", "015891", "090996", "097754", "086805", "049938", "063680", "106760", "071622", "102088", "078049", "112172", "117464", "043783", "133645", "103276", "094090", "001449", "097018", "078026", "064653", "057905", "108092", "010266", "058482", "110372", "101456", "015039", "009809", "043835", "050417", "039726", "057491", "052710", "006728", "020743", "034061", "059082", "024474", "052397", "074530", "082894", "067929", "107313", "034436", "125456", "022827", "078158", "003799", "097552", "079186", "034173", "011881", "041314", "026086", "123134", "027981", "110016", "027418", "041365", "031236", "116843", "019314", "012881", "103995", "082891", "070355", "021243", "119243", "041774", "108619", "047835", "046902", "087442", "040811", "040542", "118595", "028962", "022680", "041954", "074230", "045498", "007273", "087021", "106636", "133036", "072686", "061387", "071508", "130841", "069621", "066616", "081554", "078228", "047699", "012162", "011787", "051678", "018204", "010352", "016586", "034928", "045127", "083298", "127825", "050459", "001364", "009001", "047584", "052253", "041728", "037617", "128277", "019479", "111520", "073713", "072558", "101437", "064750", "054466", "109295", "083283", "127432", "071859", "112697", "075988", "059763", "048419", "125864", "052353", "049155", "073859", "067075", "120262", "125594", "008052", "067781", "101752", "113460", "124223", "098276", "123056", "017070", "050728", "041910", "079688", "066819", "043403", "114495", "060381", "085511", "078231", "016999", "066550", "012780", "083918", "072403", "102079", "090936", "090378", "058229", "017076", "030321", "130979", "090833", "079547", "041648", "035595", "018212", "123057", "090552", "109846", "010826", "102751", "000453", "075518", "127403", "048138", "085954", "051802", "107704", "119514", "036954", "038774", "016992", "023458", "108323", "056854", "054355", "051983", "117920", "094406", "036945", "082848", "100113", "132229", "119916", "121873", "036350", "062298", "044782", "024965", "095391", "073581", "114064", "130503", "019035", "047209", "106590", "101695", "073610", "044138", "048413", "071930", "021805", "017743", "081368", "114920", "098240", "009791", "113170", "109554", "078073", "133085", "002038", "065005", "085922", "005543", "010750", "014784", "092731", "047345", "084287", "016995", "044552", "060853", "019305", "014965", "014032", "058063", "003931", "119684", "040580", "049683", "066050", "066187", "093763", "095653", "013264", "058929", "132460", "120809", "122631", "099524", "122392", "092456", "021786", "032076", "087368", "127473", "009340", "129254", "104816", "120781", "077887", "013580", "034726", "024364", "058645", "016678", "104407", "096453", "100640", "067790", "101837", "116218", "072015", "132067", "080106", "072542", "111613", "103525", "130289", "000094", "109379", "009030", "081436", "072461", "011550", "006676", "059636", "029383", "052820", "118669", "057056", "079001", "070655", "058205", "002677", "057546", "104121", "089370", "068937", "111921", "041329", "058896", "010761", "089160", "107615", "112318", "010634", "067095", "058438", "120679", "100021", "062282", "094007", "056577", "105269", "031192", "044484", "080092", "115004", "027838", "031120", "003458", "001034", "121508", "048543", "086669", "098139", "127019", "107982", "040148", "109961", "074247", "096897", "073934", "080494", "014377", "071318", "075763", "001310", "054575", "005261", "063211", "086899", "050954", "130950", "074074", "126204", "018238", "129434", "079610", "030090", "103570", "022957", "001728", "122124", "126157", "002852", "017313", "124033", "028145", "063862", "077618", "058533", "037814", "115192", "098501", "131590", "027847", "121547", "035480", "103409", "082804", "031838", "027220", "007079", "073494", "129200", "000308", "094604", "117197", "113487", "121073", "068482", "039737", "116877", "031193", "007965", "104087", "126548", "016088", "127054", "056569", "005786", "031643", "062060", "132296", "059506", "131086", "055118", "083277", "122676", "042212", "062657", "053302", "076038", "043026", "051439", "062946", "062233", "014976", "071788", "109824", "074458", "013130", "089536", "105688", "011445", "039717", "129787", "080119", "019982", "120521", "007565", "111450", "075605", "025283", "040728", "097682", "039671", "124810", "103083", "064326", "074699", "057806", "007155", "064101", "103872", "046519", "130400", "063931", "041465", "132942", "129873", "101571", "126482", "112634", "126800", "039602", "108165", "006924", "106981", "088346", "003970", "126846", "058171", "114635", "046743", "127475", "103451", "005159", "121952", "014798", "003443", "054593", "073164", "115039", "023557", "125526", "105392", "083793", "087650", "058822", "022288", "126555", "104058", "017940", "113759", "004367", "057774", "085515", "130543", "094638", "023412", "116740", "095646", "122086", "036402", "024433", "071933", "066538", "129650", "071798", "020246", "097907", "003090", "119698", "020192", "066611", "082149", "111983", "033972", "096932", "088552", "013458", "098569", "026531", "024412", "078770", "102916", "090554", "114731", "107514", "061088", "050311", "080746", "086556", "057319", "063646", "069078", "045822", "112662", "018939", "036479", "041015", "053346", "048021", "053711", "061550", "062547", "038428", "026641", "016527", "067654", "077250", "030988", "101959", "089748", "090866", "101454", "108282", "004288", "021607", "117651", "035164", "022724", "114196", "083836", "056033", "126107", "076183", "128962", "026891", "072642", "111220", "084886", "098426", "122149", "012673", "111981", "121269", "056835", "015985", "093170", "118499", "071812", "012320", "090368", "028650", "062488", "001954", "064865", "120729", "059734", "113930", "087396", "034261", "117204", "129986", "070422", "008054", "091691", "007025", "036864", "100341", "016076", "118880", "050742", "062220", "100044", "001902", "064545", "039467", "000142", "021474", "113711", "007707", "094020", "123091", "003651", "104873", "115565", "016082", "107944", "049201", "098335", "005931", "031322", "073466", "113049", "132553", "117470", "074965", "030112", "092945", "112059", "047967", "097618", "118061", "008626", "081678", "127667", "066776", "037177", "065936", "098734", "047585", "047201", "000846", "059716", "040978", "055320", "018643", "002468", "035418", "131236", "015434", "121333", "130872", "065978", "046833", "054667", "128084", "114988", "024097", "044156", "031570", "011629", "073836", "026714", "119036", "070386", "021917", "100108", "058403", "027874", "128588", "122571", "084888", "017708", "102754", "113891", "087681", "009131", "117682", "063184", "109261", "044297", "057568", "006966", "001045", "115469", "005611", "069716", "019151", "062403", "007988", "011114", "028623", "077254", "109280", "031326", "097288", "132698", "016458", "021781", "124088", "006329", "118042", "107331", "014394", "034548", "116961", "104398", "115673", "052726", "027396", "109557", "115970", "117647", "078993", "044784", "029214", "079598", "106001", "006516", "108464", "037493", "042572", "120573", "019382", "063839", "018779", "017425", "102351", "082573", "016341", "058384", "125331", "042316", "063604", "034000", "105553", "061291", "069558", "026238", "121081", "111261", "029478", "079969", "071309", "014712", "092205", "083171", "013250", "066250", "025490", "064484", "105099", "096671", "027775", "007885", "071008", "039793", "047257", "113825", "046193", "048585", "042795", "002936", "105917", "026130", "090377", "006342", "089494", "068570", "026983", "000768", "104315", "079336", "005795", "039489", "064382", "058285", "093531", "018153", "072883", "047777", "123116", "035043", "068401", "124673", "061367", "021191", "025979", "050158", "118259", "006645", "091495", "096624", "036612", "009901", "021190", "118777", "110416", "130878", "024695", "089298", "084761", "068708", "076896", "116320", "064336", "066573", "069526", "066954", "125970", "073393", "091801", "133327", "077659", "000886", "110986", "099080", "002984", "084214", "054863", "102838", "066344", "083625", "082122", "052506", "018695", "059484", "021078", "006171", "133508", "093078", "029140", "061674", "009480", "026825", "031180", "033651", "032567", "011575", "109965", "047084", "098273", "118021", "125656", "057937", "088812", "040697", "120604", "039242", "116371", "047882", "112323", "063766", "046215", "101112", "026143", "110003", "087920", "059094", "068649", "029272", "011102", "042494", "070589", "089957", "124579", "007507", "039397", "030911", "103041", "078679", "035399", "039544", "034686", "035827", "050431", "048780", "064921", "040557", "086628", "062256", "098128", "029171", "109722", "026442", "069074", "115232", "027217", "080964", "065635", "043753", "107164", "046561", "056801", "129592", "007780", "114110", "119610", "036975", "105744", "061692", "120364", "025801", "056766", "108005", "033786", "042815", "029874", "066182", "061966", "052043", "090515", "007915", "006636", "021253", "111643", "044403", "059587", "053970", "067003", "045482", "106293", "037296", "031926", "039545", "086755", "050877", "119398", "101254", "073315", "015939", "094574", "106588", "099108", "047057", "071385", "024854", "013588", "111245", "039132", "119462", "128316", "042893", "076103", "065144", "113920", "104757", "079413", "027511", "001804", "119744", "111191", "112416", "075991", "086068", "070030", "116341", "096567", "108917", "107405", "129865", "114552", "018167", "098299", "019448", "102075", "077443", "057006", "072024", "003779", "046083", "038293", "060052", "102138", "087987", "067841", "064685", "038102", "086423", "020444", "028272", "024352", "065215", "061952", "053457", "095152", "074561", "000795", "006594", "117079", "015485", "021642", "077878", "052470", "024123", "101823", "061948", "054395", "117843", "056406", "091103", "010590", "104216", "106245", "089412", "102418", "128992", "124649", "031819", "064150", "128697", "060724", "117741", "030965", "073607", "039247", "122780", "006387", "011674", "085946", "092429", "040044", "052972", "014262", "029275", "019227", "057243", "035055", "102861", "009402", "027216", "035396", "082660", "110116", "021077", "020792", "101565", "062259", "080927", "113842", "075555", "106756", "012782", "028803", "088822", "068487", "077579", "078548", "124162", "093956", "003708", "070351", "097210", "098482", "053454", "079371", "023606", "060941", "128719", "114146", "088434", "059448", "046622", "006701", "058395", "122758", "087910", "082625", "041337", "059022", "128433", "084190", "017977", "012967", "077462", "085792", "074639", "014160", "011129", "004221", "017881", "091800", "059490", "079022", "123327", "022736", "039881", "128728", "088975", "001785", "132762", "034311", "047682", "013636", "121160", "068741", "060832", "035599", "109630", "044866", "125653", "091029", "015357", "074750", "115496", "062464", "001186", "026831", "091534", "054246", "119671", "058361", "083613", "022016", "053534", "127721", "046731", "080041", "123025", "028663", "040501", "123551", "114851", "068155", "095061", "066751", "027427", "048955", "054283", "094782", "133624", "119613", "005700", "124087", "065953", "110520", "015446", "034278", "082693", "057814", "000160", "008558", "045332", "072341", "017125", "032083", "133254", "131854", "052865", "009331", "104517", "055174", "059641", "107658", "071450", "002411", "104633", "088167", "126916", "090363", "038334", "020147", "000066", "080800", "054717", "026843", "022440", "102059", "078050", "040712", "125560", "121750", "104942", "106109", "082323", "018950", "051966", "070055", "125676", "074791", "115094", "011423", "067494", "045562", "013925", "058495", "084409", "074680", "058791", "025367", "045184", "118249", "090401", "082627", "014050", "130985", "048141", "033129", "108508", "051150", "132500", "083677", "033763", "029771", "048507", "062445", "077279", "057566", "069536", "029863", "023934", "075249", "041520", "094062", "072855", "078491", "022928", "004535", "032059", "125140", "122153", "064620", "032375", "003845", "123465", "037708", "017985", "003645", "128683", "096906", "100312", "010259", "086128", "104548", "034676", "055950", "085123", "011827", "117736", "005510", "116754", "112734", "059354", "031785", "057508", "097487", "059796", "109417", "038625", "028550", "119663", "017040", "007765", "006770", "036265", "004025", "099269", "030812", "122067", "031060", "049346", "106000", "041041", "061463", "022908", "069498", "030348", "013892", "127008", "068691", "088317", "081606", "010081", "009994", "073373", "024098", "059087", "072458", "011398", "049073", "065551", "115224", "069026", "078857", "008619", "003503", "062291", "060646", "013907", "014011", "103929", "088500", "046675", "013341", "017478", "074775", "104542", "056710", "123529", "108852", "077183", "093467", "052561", "126247", "011111", "113640", "073064", "054094", "048581", "052906", "020814", "095568", "104869", "000930", "108978", "046596", "069722", "083154", "060072", "097157", "089912", "056562", "122073", "105486", "096361", "028158", "083459", "030285", "060857", "012250", "050355", "068183", "111977", "082938", "005869", "075942", "085944", "006399", "065652", "096785", "034769", "025431", "063876", "034175", "054608", "117610", "045291", "020763", "106544", "071978", "025924", "082531", "125931", "071867", "052390", "046929", "077157", "126425", "057868", "082524", "104966", "006340", "064072", "124550", "006299", "091561", "109802", "101657", "073945", "018409", "128774", "132910", "133146", "053665", "033237", "113358", "031209", "117853", "100961", "067925", "040393", "068481", "050849", "121856", "107955", "035152", "031163", "100646", "049184", "062261", "125847", "064736", "022250", "033713", "102973", "052572", "081921", "041551", "029549", "001341", "110650", "038422", "015135", "076874", "023154", "111743", "081444", "093936", "080535", "129834", "024811", "079395", "052223", "054439", "116063", "046702", "008279", "038801", "080590", "071513", "011967", "009020", "123566", "036572", "067868", "092806", "101545", "131243", "003874", "066861", "092938", "047574", "039729", "080094", "075281", "013688", "107768", "099068", "064864", "085135", "096606", "031480", "123399", "029387", "023967", "032769", "000154", "127676", "116757", "058157", "032970", "060546", "132228", "014237", "065335", "070410", "046429", "001314", "016485", "048613", "031212", "037269", "067585", "121889", "005806", "076553", "084340", "122373", "088205", "023813", "023180", "109102", "045317", "102019", "019630", "000067", "035709", "093598", "073160", "043165", "035450", "096527", "064214", "042819", "091640", "090953", "075822", "127483", "133294", "055935", "045995", "001084", "077970", "060618", "049907", "059540", "111057", "091065", "052942", "054818", "078011", "089846", "089441", "062736", "072183", "048998", "092235", "075226", "114659", "006830", "087751", "106935", "009608", "095059", "117864", "062640", "121505", "111386", "120912", "095324", "003351", "062890", "124484", "132003", "041100", "000626", "071278", "101301", "048444", "122262", "108130", "026751", "056594", "128151", "008975", "034103", "079156", "064048", "009814", "006948", "012319", "028585", "079038", "009193", "022997", "098830", "020098", "087713", "104073", "062392", "049506", "122542", "065293", "048811", "088904", "096168", "041922", "024224", "038636", "130279", "079572", "010231", "047093", "122774", "041550", "130903", "078984", "094004", "089169", "104528", "066856", "117104", "066051", "093428", "032071", "033945", "017049", "112467", "037579", "006313", "019749", "034248", "032653", "115176", "035181", "012738", "079020", "095713", "130694", "043565", "034467", "046890", "122163", "090218", "057735", "104055", "089100", "068696", "052298", "075424", "052328", "104296", "099654", "074691", "075431", "065464", "086317", "091163", "062043", "018210", "016492", "014341", "125349", "085528", "065618", "073952", "090835", "117210", "016669", "015074", "041319", "077088", "052509", "014794", "006918", "114207", "037298", "130788", "014969", "112977", "072775", "079354", "037445", "057262", "101744", "096950", "000970", "032921", "020031", "111423", "072900", "128007", "003626", "041838", "098880", "002475", "106276", "029426", "019796", "061557", "020180", "073536", "031872", "132356", "055039", "012494", "086268", "035656", "027280", "001857", "043247", "108222", "101235", "122853", "030247", "049371", "008276", "045756", "130062", "030622", "019601", "088382", "037255", "122765", "070009", "060077", "020506", "035147", "113550", "042404", "008060", "040865", "122187", "044516", "108652", "107373", "012550", "040512", "114199", "000581", "046326", "057831", "051042", "072488", "068177", "082635", "039286", "120448", "094612", "057701", "131717", "079821", "009914", "001891", "116676", "000276", "017520", "052039", "005389", "075078", "121513", "015574", "036956", "119717", "067771", "092743", "026244", "073816", "006295", "107585", "060792", "025760", "042646", "120960", "101255", "019288", "092366", "012017", "121441", "075702", "103510", "047784", "037669", "013155", "089907", "120900", "000063", "043764", "113427", "048043", "055114", "105923", "041103", "095624", "123037", "009851", "044651", "013885", "043306", "060762", "091980", "104791", "055107", "132087", "002351", "119846", "086354", "081646", "092586", "117092", "115640", "014683", "057658", "074331", "001427", "078194", "133630", "029319", "051702", "126304", "027001", "082202", "066641", "113279", "016073", "108821", "077957", "018330", "088265", "012315", "033950", "031432", "108849", "113028", "093357", "133606", "068679", "058393", "089981", "001823", "046157", "050935", "030260", "002167", "112326", "038717", "113257", "061824", "067764", "014225", "094864", "006744", "005874", "094415", "035907", "032343", "026218", "028212", "035324", "072334", "031220", "014180", "001009", "062070", "130652", "114785", "131004", "105906", "046426", "040460", "041117", "040693", "036561", "066501", "117069", "009438", "032396", "118965", "099671", "067284", "072737", "106385", "128186", "072414", "110303", "109355", "043388", "034460", "082756", "051806", "103067", "008644", "100815", "053180", "102085", "090342", "118081", "129725", "107670", "043089", "002858", "068997", "069569", "104536", "034788", "012402", "070276", "125652", "077736", "110451", "067817", "101702", "020623", "109561", "023759", "003488", "034251", "117410", "117081", "127600", "026929", "122879", "086408", "065967", "103285", "029809", "108826", "057881", "073345", "036136", "050101", "079718", "000916", "021345", "102579", "028298", "019014", "063953", "016954", "008315", "097983", "111856", "062662", "018986", "048682", "119261", "031692", "077178", "084181", "082833", "007031", "129090", "099991", "062829", "058504", "069807", "035640", "061192", "045176", "132116", "129630", "107993", "090977", "006505", "127020", "065994", "011639", "030263", "051652", "023025", "061283", "114837", "078651", "096764", "115539", "125715", "044034", "049804", "008413", "055574", "025357", "099119", "048284", "023768", "120104", "089262", "022303", "095523", "121435", "100731", "105057", "118364", "086079", "027410", "054949", "113615", "054605", "037231", "005732", "062109", "132038", "068045", "030527", "002569", "049518", "067261", "027806", "054369", "050307", "113715", "035135", "100835", "041793", "056557", "074820", "112088", "084472", "112491", "073146", "047743", "126228", "056755", "068550", "099074", "078152", "083754", "060755", "012624", "092703", "005221", "008962", "028685", "130864", "018967", "084100", "006439", "129662", "026841", "102656", "106821", "067169", "057746", "080316", "034535", "104452", "066236", "044474", "106751", "033157", "084341", "070165", "003555", "073838", "078383", "035350", "023323", "022236", "022201", "130748", "013729", "006939", "116198", "079754", "072790", "111766", "045157", "080314", "030097", "062669", "003832", "127189", "015296", "073127", "092694", "042670", "000869", "096106", "074311", "044181", "062969", "063262", "012857", "097401", "004610", "094610", "108685", "046584", "114155", "051093", "037693", "116209", "078672", "035894", "034840", "028923", "089998", "018359", "000356", "086683", "027114", "100452", "052751", "053699", "086004", "058744", "036555", "051375", "113110", "084174", "115980", "088715", "023429", "078132", "116768", "031453", "072440", "004461", "030815", "030328", "109558", "123351", "044546", "113605", "040099", "098864", "046467", "066981", "031130", "034846", "080818", "036126", "049723", "129439", "082983", "122170", "085947", "064867", "078019", "097572", "034293", "098811", "036970", "079929", "000588", "108475", "095740", "022710", "032511", "117220", "027081", "023622", "031871", "115237", "043076", "059486", "033403", "040636", "076309", "121143", "029384", "076250", "015671", "007228", "097343", "008256", "007024", "124438", "032532", "118736", "003467", "072430", "066667", "121628", "006640", "025053", "106507", "034975", "028967", "107686", "121422", "043812", "122952", "065195", "133179", "056983", "086834", "000049", "048094", "091702", "054560", "067053", "071310", "101050", "082892", "078314", "102835", "012934", "062458", "118577", "018689", "036849", "084672", "109805", "110476", "057070", "014075", "124514", "040525", "130241", "050951", "089281", "057373", "078556", "020240", "014238", "071920", "085423", "121016", "102862", "007173", "131275", "120317", "018771", "028606", "084239", "011537", "032462", "113079", "018060", "123937", "113262", "037229", "048337", "062767", "071439", "001306", "011188", "075017", "118333", "041926", "120949", "093847", "063716", "041722", "052511", "060018", "113532", "047086", "098091", "000606", "033396", "070584", "085524", "073997", "062521", "060085", "015142", "007640", "083478", "061070", "009224", "072581", "113340", "028274", "114636", "095465", "070994", "119734", "060668", "093734", "096218", "014457", "028933", "052338", "103905", "104912", "121680", "034688", "093242", "113036", "069430", "097814", "132968", "103587", "067894", "088437", "083550", "028646", "102661", "107260", "082320", "086763", "041833", "056519", "030532", "099984", "052565", "070870", "038732", "076520", "012378", "015905", "016758", "039768", "057959", "005334", "103831", "058258", "061343", "047466", "065063", "042915", "103109", "067217", "005775", "012475", "106434", "124272", "029858", "124372", "015400", "048969", "083660", "041714", "057855", "004102", "047632", "105520", "005161", "112453", "086682", "069246", "110078", "084228", "075026", "044690", "102573", "020284", "071198", "091650", "093147", "084537", "074419", "112619", "131807", "125318", "037405", "034497", "050942", "107650", "130740", "063271", "062863", "058374", "032741", "064440", "132165", "074223", "016011", "104004", "109253", "122722", "101176", "039491", "006824", "090905", "099226", "076030", "079922", "119418", "011522", "119927", "107487", "020750", "024766", "083922", "011257", "071471", "066675", "068748", "073048", "076952", "108018", "090729", "107191", "046357", "047883", "048310", "087191", "040732", "129502", "119309", "107052", "105333", "032052", "008948", "079344", "117045", "006574", "017504", "095756", "005296", "070467", "123578", "128894", "098030", "069317", "036260", "038454", "013258", "118029", "010875", "037911", "096854", "028200", "024671", "120140", "046615", "060965", "040167", "094304", "080709", "050845", "106696", "083908", "021847", "020524", "019485", "080909", "075643", "072791", "035592", "089369", "113440", "047473", "072588", "039195", "003111", "027486", "108149", "110870", "091037", "066527", "076208", "016938", "132384", "119448", "013308", "011298", "116412", "063320", "128478", "036658", "031777", "035190", "061866", "008586", "035094", "075139", "006068", "010211", "024356", "018948", "117500", "068619", "099589", "039440", "084525", "045911", "016979", "009300", "081551", "084164", "125205", "094878", "093588", "059071", "051558", "042275", "007467", "027743", "047750", "042919", "040669", "108383", "091184", "101046", "066148", "103183", "024939", "023099", "120232", "114980", "087971", "041158", "004981", "047683", "038824", "130999", "075996", "116491", "080287", "112997", "000944", "102170", "130309", "082067", "006579", "019490", "054177", "034152", "124466", "051085", "070314", "132536", "125362", "097253", "132022", "095268", "100900", "102007", "050528", "099872", "010857", "067042", "070113", "128924", "012650", "097792", "100022", "091042", "031990", "019697", "064493", "096007", "067637", "036579", "008169", "104975", "109525", "105398", "044149", "072415", "101164", "131393", "081557", "083254", "007275", "100045", "036517", "101618", "054966", "060768", "088212", "073825", "110104", "006765", "040417", "115937", "121661", "007843", "007745", "041115", "055657", "069066", "077112", "016295", "073656", "125616", "117046", "023907", "130250", "066629", "096647", "031127", "113190", "083180", "094258", "097591", "003258", "006768", "004668", "050555", "073768", "041734", "098037", "046396", "101527", "037261", "007546", "098580", "105662", "056895", "047273", "126656", "017220", "025577", "026095", "064883", "056512", "011001", "008032", "044163", "014296", "032430", "026958", "065150", "042737", "065416", "077344", "039383", "023371", "087314", "043259", "118960", "031273", "076754", "008180", "120547", "070950", "102549", "015788", "067352", "054293", "052396", "124532", "004512", "072372", "057464", "062169", "000297", "074187", "053915", "022138", "028579", "036367", "031372", "054421", "115076", "111745", "039789", "027803", "042449", "075980", "023277", "040931", "130795", "082483", "120515", "068950", "066719", "115383", "050810", "091212", "006738", "030011", "107461", "045811", "015048", "022354", "064037", "132304", "127111", "118051", "013578", "057435", "117536", "039266", "005405", "061371", "004177", "081372", "080419", "122977", "058357", "016737", "033618", "038420", "047070", "117170", "085258", "057025", "126071", "061752", "093440", "001122", "049096", "046805", "110816", "052660", "030735", "129326", "123157", "101573", "133569", "060896", "072924", "112970", "063794", "102676", "123058", "047555", "004443", "052203", "114355", "007129", "022766", "074369", "067652", "122821", "036277", "104088", "003671", "104790", "000677", "060759", "001838", "125909", "117004", "130312", "048181", "004906", "101698", "050689", "013560", "065784", "072470", "118046", "024993", "098533", "106048", "118678", "125643", "002268", "020150", "042845", "082103", "086134", "030050", "097766", "075745", "022297", "009769", "126028", "115376", "090338", "029245", "030169", "067015", "107106", "038457", "043951", "034980", "006609", "057051", "080718", "011476", "050818", "099395", "126594", "131454", "113748", "008193", "050856", "023047", "048236", "042849", "117498", "078939", "054938", "077700", "058919", "074196", "022902", "109704", "123290", "109653", "039904", "051080", "112214", "085799", "042746", "058886", "059236", "113458", "086141", "005528", "119881", "045842", "044500", "132803", "010483", "109198", "041528", "017243", "017517", "111582", "038165", "126401", "114870", "027123", "019302", "070038", "025292", "005762", "105397", "081916", "036084", "062558", "084958", "114421", "121198", "026342", "061904", "125431", "098346", "051174", "079602", "120272", "075201", "036872", "006121", "022910", "119313", "069521", "056810", "022965", "021707", "029971", "094718", "063392", "046185", "062175", "000318", "027888", "072245", "039209", "039803", "011328", "015165", "001187", "048835", "132041", "094370", "061751", "097257", "132680", "125093", "071155", "119239", "125329", "086698", "048264", "027682", "077233", "061700", "061972", "022411", "041730", "073381", "069311", "057448", "118673", "061087", "082695", "076965", "128087", "064405", "011653", "128097", "120315", "057013", "130783", "067465", "025208", "032838", "043762", "093609", "090900", "027184", "066901", "016182", "101977", "012906", "022399", "082414", "016673", "058209", "006436", "130811", "024915", "066432", "124441", "059095", "010361", "080977", "098480", "075051", "047621", "063368", "068290", "076655", "079304", "065662", "076391", "052642", "102885", "044635", "025826", "081341", "069520", "025280", "065214", "113935", "120090", "026098", "018179", "115697", "058537", "047133", "079337", "037912", "119348", "045506", "045727", "065359", "081505", "008959", "089407", "024564", "043425", "126564", "104630", "043308", "016933", "098278", "089822", "108616", "030313", "133418", "128545", "114497", "084658", "077832", "045999", "034811", "106785", "030825", "103110", "082078", "020074", "040399", "018582", "090796", "084849", "062475", "013731", "075592", "068467", "102091", "088539", "132615", "004982", "046641", "123211", "076934", "051799", "019879", "016013", "039400", "082346", "107871", "128978", "036881", "032571", "103116", "080311", "047074", "110747", "045293", "004391", "084199", "099342", "032545", "063116", "048750", "116327", "079260", "081868", "010698", "065491", "027317", "083821", "104619", "103396", "018800", "119668", "130135", "067355", "045757", "085610", "069884", "047921", "118870", "029696", "114337", "057018", "113328", "072339", "114391", "103584", "069005", "094512", "016784", "010586", "087261", "101507", "016044", "072874", "116520", "124561", "103920", "127754", "062376", "119030", "028745", "111154", "026426", "069153", "069729", "132529", "026381", "102465", "053136", "005460", "058042", "053152", "121059", "096391", "066233", "070699", "090887", "097208", "097771", "043439", "074907", "108940", "130640", "046204", "103213", "126777", "049527", "058478", "041020", "127889", "039638", "021318", "126703", "046102", "081257", "045934", "033217", "124435", "070703", "120587", "041888", "088826", "049566", "005767", "048500", "046367", "064448", "027729", "036543", "079187", "123627", "031994", "108507", "131524", "075992", "090462", "057091", "102427", "120933", "098990", "034068", "058412", "042020", "107781", "080240", "128854", "110639", "101314", "098290", "117274", "117176", "052208", "007734", "007003", "048409", "039380", "017566", "107225", "059599", "041889", "028904", "121477", "059648", "086179", "057068", "119172", "105989", "037001", "018719", "048737", "063715", "020225", "092414", "013533", "086159", "050686", "022577", "046830", "105859", "008244", "008241", "122363", "097167", "029682", "064038", "092613", "028785", "071673", "095462", "057110", "063276", "007197", "084306", "046956", "068991", "033263", "043447", "031522", "112770", "052449", "088597", "096662", "002562", "102775", "017418", "093502", "084149", "087136", "014797", "045260", "119986", "080978", "109766", "070145", "127404", "035358", "103847", "110163", "105849", "101256", "016383", "067436", "046274", "056263", "035103", "018099", "060863", "061163", "019306", "119404", "117930", "074313", "037418", "096724", "072236", "109746", "073310", "018448", "091182", "034941", "030963", "041956", "021370", "010686", "080973", "105729", "099411", "061923", "105606", "071191", "027384", "001399", "081704", "071737", "056018", "033167", "084807", "086236", "024475", "037999", "127534", "003942", "001573", "056000", "000229", "122318", "094205", "071028", "109484", "078223", "020511", "017528", "013210", "125131", "010903", "133751", "045665", "098927", "088675", "126310", "068106", "028294", "099681", "078466", "105248", "131778", "058274", "102100", "027752", "013554", "112427", "110099", "087176", "019861", "040839", "100602", "086575", "024129", "131152", "054934", "086747", "074494", "064488", "113006", "121795", "113886", "003064", "114276", "068083", "102512", "063859", "065412", "127447", "100221", "036974", "097936", "058415", "020580", "117389", "050701", "024709", "092392", "097528", "036374", "076077", "109490", "051757", "084787", "081721", "115806", "065471", "100546", "124686", "031658", "020061", "082888", "012156", "050749", "130207", "076144", "088791", "036319", "092312", "100927", "090829", "059390", "083465", "074178", "080476", "116104", "066512", "017233", "081760", "076141", "078386", "080174", "004281", "096047", "095985", "050317", "046701", "091927", "125527", "066398", "127208", "039769", "073754", "064512", "006193", "120833", "004490", "044984", "017092", "062619", "114373", "130802", "108392", "119184", "058898", "093682", "044614", "085830", "062960", "010274", "114042", "049486", "077147", "054688", "032495", "045067", "102522", "103063", "121174", "020827", "019208", "043246", "072389", "088356", "004397", "130339", "064224", "127185", "021556", "095131", "023046", "124219", "129810", "039538", "040578", "009347", "071442", "054384", "050648", "017854", "023714", "085724", "054718", "095447", "119301", "125030", "111853", "022403", "008799", "101113", "025513", "077812", "102799", "081361", "055106", "084271", "130551", "095858", "027116", "085108", "070259", "004363", "082516", "038288", "120789", "067155", "058304", "082257", "128612", "090747", "028076", "058610", "016236", "044453", "007551", "094331", "081406", "039955", "010262", "081912", "042196", "095627", "047890", "104188", "028091", "131421", "124728", "016115", "064455", "074227", "081127", "012454", "116748", "064427", "109100", "017782", "015123", "053605", "105275", "113489", "107126", "042467", "098841", "049624", "088230", "062494", "063948", "115170", "031232", "043061", "052548", "086219", "130568", "127651", "020118", "052842", "071903", "098419", "028734", "024303", "007917", "114016", "032186", "017288", "085886", "112827", "097224", "133556", "021226", "107451", "004305", "053774", "001178", "002135", "101103", "052339", "130490", "047525", "040995", "004907", "034150", "091450", "021922", "074011", "125485", "016993", "040396", "024670", "105444", "038292", "084415", "035641", "095907", "081806", "065572", "013541", "102415", "001716", "078722", "106970", "056884", "129902", "070376", "126390", "001261", "008434", "083623", "049556", "039099", "103596", "131161", "102189", "020830", "110872", "096286", "020067", "118505", "088209", "009203", "061810", "001642", "026668", "056658", "090168", "012009", "074735", "019556", "024335", "123041", "114502", "074173", "068168", "075808", "039330", "010345", "065118", "099797", "092796", "023462", "007867", "000665", "128707", "035542", "066800", "102690", "004066", "068670", "046494", "069835", "101193", "087863", "024059", "120356", "119089", "084750", "007657", "085086", "051890", "018011", "058579", "002481", "027553", "115594", "011137", "046348", "098831", "014464", "091999", "125255", "024591", "100034", "011326", "061256", "133761", "080727", "016602", "101084", "012046", "104984", "013291", "124460", "122244", "058647", "095818", "119062", "118304", "058167", "035761", "131689", "020527", "105140", "035249", "012465", "120158", "036291", "039474", "006007", "079362", "079369", "009629", "123926", "010596", "111006", "023387", "042210", "033872", "092948", "122120", "123863", "028657", "006780", "099607", "006297", "009458", "005508", "007372", "005330", "023308", "034894", "133666", "102643", "068657", "118377", "032819", "012008", "015940", "050536", "021512", "085104", "093970", "056711", "013613", "028684", "067457", "133841", "130305", "001337", "006002", "064709", "105064", "034384", "105903", "114200", "068781", "003341", "130395", "024091", "057564", "017086", "127464", "057893", "115374", "014367", "097982", "126833", "086117", "104713", "117285", "034357", "131207", "071400", "018790", "007371", "067915", "057995", "025644", "060128", "124038", "100711", "018163", "069991", "071664", "076386", "067447", "040038", "065352", "016577", "098563", "071440", "114092", "019637", "063812", "011797", "067312", "068981", "081458", "039667", "039321", "114425", "084818", "117655", "082646", "038452", "022608", "078259", "081831", "017882", "080668", "034318", "089485", "093040", "073477", "039495", "118792", "108820", "043840", "066730", "097670", "031210", "046419", "015657", "088099", "111424", "035080", "066293", "047314", "065069", "085601", "040155", "124805", "049447", "026391", "027135", "113563", "015693", "050095", "028551", "009677", "124843", "124016", "015539", "077997", "066946", "076907", "044090", "029528", "126579", "127730", "124934", "083187", "076337", "009128", "063312", "077105", "026743", "047363", "123924", "129568", "027936", "077236", "075192", "120803", "111815", "067534", "073528", "083618", "001922", "052371", "036553", "050368", "087900", "068653", "071950", "055059", "073740", "084268", "098481", "039290", "109957", "057961", "077440", "098412", "105480", "001935", "133693", "059280", "120790", "127584", "034304", "104564", "010394", "092940", "063777", "022667", "012869", "043850", "117390", "021477", "120326", "111472", "041990", "121251", "074874", "121730", "024089", "099702", "125845", "093143", "081962", "030725", "034519", "035799", "085223", "067009", "080082", "080436", "080741", "016001", "112860", "023311", "039875", "121587", "080564", "044272", "070473", "005647", "071250", "015854", "051239", "088419", "049586", "011271", "119699", "053701", "087456", "089459", "089583", "060073", "092134", "022327", "004688", "113140", "018446", "087716", "057827", "114966", "047114", "059853", "035972", "017074", "000604", "017295", "004842", "024055", "027415", "033732", "034622", "096095", "015864", "130704", "098599", "080585", "101075", "027388", "109418", "002081", "102598", "018125", "115362", "106481", "126149", "051667", "128032", "062750", "103408", "062077", "033924", "032390", "072328", "094405", "000537", "022391", "058249", "010138", "057457", "099134", "126299", "023603", "132028", "019680", "132129", "025629", "035431", "124084", "101516", "039499", "060702", "048035", "055926", "021367", "131257", "020218", "074978", "112910", "004994", "048908", "036431", "101945", "056111", "116403", "054860", "024068", "047018", "122754", "076528", "099523", "093020", "073088", "027176", "074250", "049977", "041382", "070200", "122510", "058617", "063776", "084052", "047612", "114582", "093446", "094582", "110629", "100648", "097825", "022117", "125737", "068827", "030250", "120373", "067076", "081813", "087820", "085749", "045931", "001893", "010610", "115471", "108306", "114121", "020233", "116349", "008865", "098398", "067980", "011201", "035105", "095439", "109445", "050522", "101212", "056508", "019850", "020258", "127950", "060045", "000075", "004841", "097311", "097945", "013549", "012047", "012557", "109570", "045877", "091102", "004385", "107137", "039342", "007068", "123556", "009557", "034486", "090612", "028503", "109712", "130262", "072516", "019676", "091977", "056224", "131772", "062513", "091183", "081647", "006797", "092083", "032174", "125305", "061822", "074372", "017802", "005169", "054898", "019666", "051297", "077154", "020992", "098002", "025692", "060279", "101549", "131118", "069928", "112762", "131797", "047722", "082025", "040813", "133309", "128747", "129931", "049039", "109775", "101654", "079353", "129186", "034315", "001475", "071042", "001152", "053990", "122052", "093169", "089174", "071999", "129623", "131037", "131592", "025191", "131287", "049048", "085236", "010383", "104706", "047753", "048432", "099914", "118016", "100909", "118148", "019779", "077520", "111814", "083914", "060978", "030341", "037798", "006208", "111205", "059058", "026004", "133186", "016120", "032013", "069628", "036783", "089444", "110540", "110913", "130854", "017632", "109399", "008803", "071086", "005615", "120178", "050462", "005812", "061167", "089092", "037471", "125836", "017759", "034215", "018749", "080760", "058049", "122851", "000041", "106741", "080339", "059833", "064525", "122271", "023480", "041092", "006707", "081559", "060916", "023915", "013117", "034388", "020654", "032453", "113338", "035357", "098632", "015334", "041631", "068105", "053358", "114223", "008881", "102527", "111686", "072665", "026971", "019744", "074046", "049055", "019612", "117003", "022505", "124960", "103644", "130732", "067007", "124032", "071225", "062016", "027869", "004909", "083845", "031272", "106647", "005397", "098846", "015839", "050635", "086658", "000627", "118519", "090279", "029706", "064508", "043941", "037735", "013803", "078712", "080437", "103609", "000367", "002265", "028710", "099405", "071606", "074916", "001943", "121226", "122243", "106029", "032768", "070248", "084050", "046276", "010285", "022929", "100629", "059181", "092365", "001484", "024109", "047986", "108023", "002114", "122141", "034070", "110828", "048574", "111282", "119798", "022381", "063688", "085302", "057236", "073360", "077777", "020034", "128586", "031581", "007221", "063383", "087772", "108106", "018890", "032679", "067802", "002755", "126108", "090867", "057555", "034736", "116527", "026818", "028446", "015481", "017675", "098033", "034665", "030292", "021920", "101631", "009365", "049840", "071068", "039636", "057859", "118104", "009820", "018376", "093496", "087931", "082203", "058322", "096451", "018032", "031398", "071312", "069181", "088816", "130047", "091395", "084116", "118964", "063537", "042528", "111145", "033806", "051225", "031086", "078929", "056468", "044828", "113644", "018911", "088883", "095672", "027768", "091737", "004268", "106947", "122845", "129700", "030640", "089457", "095398", "104520", "043034", "035774", "030455", "060427", "088156", "083904", "130140", "000035", "082256", "082765", "016907", "013482", "105880", "076558", "020126", "031558", "045552", "034957", "115807", "032590", "072469", "073371", "118798", "104986", "017705", "022829", "026071", "060914", "067370", "017941", "081192", "056515", "125432", "126298", "133462", "111014", "044086", "059331", "084666", "037092", "110738", "120856", "113313", "021432", "002998", "046515", "103193", "053501", "046647", "114035", "106470", "029349", "017701", "031188", "043059", "006356", "132548", "051672", "004951", "055747", "090533", "090292", "115259", "120517", "092879", "095563", "131913", "091437", "036985", "035841", "009067", "072180", "003287", "079495", "039948", "034346", "085200", "066445", "045547", "081308", "049079", "125546", "012306", "029396", "055305", "056673", "101738", "124476", "111211", "038258", "007513", "082677", "042891", "050757", "036930", "083909", "123830", "071752", "095628", "039647", "058389", "079819", "021801", "117306", "102344", "035209", "029072", "097934", "026985", "052060", "072858", "118834", "131829", "082620", "012779", "041475", "005866", "042096", "108925", "017494", "006739", "085169", "110274", "013043", "084993", "061175", "088600", "044913", "007062", "007503", "109856", "095829", "107603", "117951", "016499", "102186", "082462", "118014", "041620", "083271", "098818", "041829", "014248", "055045", "110197", "043732", "056066", "075151", "023227", "024956", "122002", "085801", "073984", "052451", "086644", "020928", "119101", "047387", "056573", "094316", "131408", "112262", "113207", "119206", "004859", "047159", "076504", "114287", "079803", "025113", "099622", "112235", "052963", "047120", "013116", "107444", "050862", "129438", "095388", "052891", "006599", "083391", "109189", "098072", "008305", "060023", "097503", "112396", "019504", "051070", "110248", "076078", "078608", "005341", "009658", "099130", "070039", "109264", "041709", "072215", "010571", "025738", "013621", "099549", "115903", "065240", "029903", "097008", "034317", "026227", "049137", "000251", "133181", "121104", "045647", "078764", "034003", "101258", "013574", "069242", "116385", "097220", "102376", "107477", "103430", "101249", "055183", "041233", "047292", "102187", "062362", "080044", "123181", "007123", "009471", "014276", "117942", "112848", "059025", "050806", "126757", "111078", "085687", "035870", "104046", "064533", "127487", "086716", "001447", "079043", "028729", "026361", "090534", "049743", "111291", "041950", "026203", "071575", "089097", "080988", "010029", "106806", "055499", "055754", "049478", "122169", "108505", "010099", "091064", "052324", "068327", "035684", "008443", "006681", "045473", "065513", "034641", "106375", "019928", "105711", "086718", "028354", "048710", "066396", "115666", "026118", "054500", "047333", "071514", "119826", "063377", "106979", "069208", "076193", "104161", "086616", "121788", "114058", "051296", "081936", "027781", "070433", "087518", "055967", "098158", "043526", "089251", "123391", "083642", "031718", "125932", "048480", "057705", "010021", "015579", "067055", "122010", "021466", "010200", "101491", "100982", "008120", "008117", "020296", "038096", "058460", "070818", "087715", "035453", "048798", "097036", "058938", "108848", "024020", "053200", "084346", "021561", "090525", "026155", "073565", "102004", "029162", "061012", "129001", "131504", "092298", "037780", "080997", "058356", "132816", "103661", "010401", "131310", "019355", "096230", "098354", "076871", "008271", "042258", "072361", "086228", "009370", "038126", "019945", "058859", "054744", "083630", "043374", "113439", "116622", "069003", "094644", "032992", "023572", "094381", "074647", "000986", "074684", "066993", "045928", "003568", "056002", "081757", "111851", "037638", "066466", "119322", "043499", "098799", "047695", "041802", "131439", "120563", "111790", "003138", "072418", "081994", "131130", "050416", "106526", "108974", "127240", "014605", "124263", "054377", "040374", "048276", "080969", "039784", "000259", "091675", "131929", "029236", "123985", "089625", "126607", "131571", "066510", "027073", "115022", "090427", "061965", "053187", "113560", "088417", "027212", "032421", "081293", "020734", "057516", "073175", "101541", "071890", "008551", "053092", "047161", "021863", "065374", "059919", "015256", "063868", "128064", "005796", "063027", "070615", "118737", "002762", "061720", "127364", "132930", "009093", "067083", "047173", "132620", "126015", "056139", "060395", "017521", "100522", "011526", "079914", "028880", "059544", "097846", "066627", "077390", "044464", "105245", "133197", "083289", "036143", "028496", "120703", "131041", "130212", "072914", "098260", "083300", "052478", "076828", "047287", "003938", "096998", "022695", "010990", "088875", "005180", "043260", "024216", "005448", "039318", "066625", "121829", "035541", "027501", "123008", "030642", "129047", "071324", "005608", "065905", "068462", "037769", "042853", "125004", "023854", "027507", "094885", "033188", "104364", "100814", "121667", "105013", "056480", "033080", "024590", "111270", "013256", "123554", "050575", "054530", "121778", "056714", "113815", "040212", "046254", "028185", "000334", "043110", "010939", "084342", "070051", "100235", "068014", "072838", "055951", "126598", "109128", "052226", "046572", "080653", "085309", "003927", "054559", "014818", "042328", "066147", "120842", "002477", "056856", "075921", "056780", "025717", "118058", "084747", "112428", "103332", "018317", "095020", "014566", "024545", "004139", "007860", "014015", "020709", "082535", "131701", "117804", "036217", "050210", "049265", "115184", "037842", "104575", "124008", "034673", "046435", "080313", "103600", "102954", "132313", "072787", "036775", "115925", "005462", "105774", "073513", "120328", "059039", "059186", "032888", "113088", "043030", "117948", "083938", "073280", "022362", "133231", "021953", "132954", "044261", "004673", "119530", "115151", "060624", "111651", "004546", "064120", "024837", "013361", "068530", "086464", "092428", "128650", "104655", "034174", "037416", "077093", "120456", "031865", "109807", "087848", "029820", "004919", "080483", "036799", "047356", "125925", "039559", "025611", "126186", "014908", "000008", "075731", "087776", "063879", "127719", "008937", "044574", "085694", "013263", "037113", "057823", "054993", "078214", "079191", "023517", "105031", "057960", "113093", "012661", "016927", "032333", "089256", "069714", "023827", "127672", "086411", "076541", "046618", "127052", "012092", "009137", "071817", "004112", "089345", "093412", "022293", "131527", "132597", "024186", "079830", "035940", "061339", "126586", "073821", "009780", "015494", "092352", "123791", "054428", "031218", "087395", "014531", "050295", "082835", "022454", "022292", "075169", "043024", "019451", "085754", "043048", "096545", "074763", "094933", "110916", "008022", "119909", "057551", "112344", "068503", "115519", "017095", "028575", "072815", "037960", "084927", "092604", "024933", "003625", "032339", "120322", "088871", "110694", "094171", "132275", "101148", "089279", "013184", "042551", "038943", "031842", "092157", "118501", "074767", "015966", "029228", "094973", "109454", "090616", "091496", "013346", "069815", "127084", "067968", "104037", "039910", "116607", "010836", "110213", "091932", "112651", "100973", "044174", "023997", "038137", "076383", "063441", "025917", "051481", "079111", "012753", "127427", "039105", "056292", "011648", "095382", "128564", "118883", "121838", "132351", "066567", "047247", "041930", "088238", "059106", "018544", "045672", "089430", "009054", "094325", "116342", "027518", "032300", "040758", "071626", "091594", "038038", "100401", "068614", "123438", "027249", "023207", "048458", "016026", "114281", "063911", "107687", "076004", "125419", "004325", "000145", "122875", "090987", "131720", "132679", "074329", "046112", "124745", "117103", "042146", "094442", "054694", "131731", "105130", "103971", "002109", "089885", "020896", "058392", "018357", "016144", "040588", "024181", "014926", "129925", "101846", "016200", "126659", "070911", "048521", "073247", "010217", "119307", "055089", "051522", "064387", "094868", "124099", "003909", "038857", "107699", "052812", "083431", "115077", "015941", "055481", "035360", "050916", "100390", "026653", "034684", "096657", "042793", "090855", "095463", "080947", "078930", "088236", "013082", "053733", "000275", "009592", "092581", "102394", "098175", "051563", "034915", "086035", "059657", "126241", "002437", "071572", "059810", "019875", "065353", "023300", "076273", "013269", "000630", "065586", "123099", "016961", "045061", "127926", "024769", "077918", "012520", "052698", "075817", "119376", "020938", "123822", "022028", "082429", "131377", "062437", "044986", "131261", "082475", "038832", "093385", "084502", "017920", "090341", "078685", "077856", "062058", "113809", "114006", "104319", "126296", "094802", "050609", "038599", "073044", "071669", "008373", "076543", "098493", "017333", "117548", "106718", "047116", "029501", "017556", "003657", "030403", "028900", "016522", "108767", "049354", "095062", "065840", "051819", "060130", "128069", "117894", "086931", "117514", "058474", "083046", "115467", "019372", "120677", "042283", "099545", "015790", "122322", "057908", "064954", "116206", "088711", "093654", "101606", "023256", "119770", "117304", "128957", "033251", "025360", "027997", "099923", "045124", "021960", "087312", "125549", "061542", "114604", "058517", "112327", "022936", "079987", "000903", "031972", "101853", "027791", "054585", "004437", "120660", "102748", "052681", "107899", "018469", "037123", "062602", "091180", "013195", "008641", "006512", "109162", "069812", "045128", "090097", "115531", "117476", "037598", "001662", "042419", "030497", "066668", "052890", "086982", "037151", "091810", "004970", "068293", "013111", "046104", "042863", "006209", "076111", "099916", "070273", "080454", "045587", "105450", "074620", "133389", "083873", "058399", "101500", "022867", "036395", "026066", "030666", "064953", "077666", "043199", "019454", "023681", "127823", "000125", "049570", "032611", "061910", "004494", "000524", "001619", "023863", "004160", "111873", "077636", "094463", "023414", "063606", "038668", "027008", "002201", "106653", "082266", "099149", "032503", "029432", "059552", "086573", "122245", "099297", "010766", "050293", "100949", "047918", "087799", "029269", "115786", "076196", "027670", "119976", "096561", "115021", "116249", "070347", "036587", "090826", "050400", "067508", "122858", "073201", "117683", "104170", "038193", "125249", "092700", "117978", "014465", "035443", "123177", "071605", "052414", "080910", "057927", "114210", "132685", "079444", "042361", "069450", "019249", "067559", "042594", "000931", "028019", "043172", "081209", "053303", "065895", "029119", "067815", "008489", "098097", "049588", "128455", "025406", "050013", "089909", "031280", "063191", "082403", "118580", "004227", "061679", "127909", "100358", "021513", "068081", "035115", "070079", "073444", "059273", "091770", "094669", "107429", "066315", "053693", "047219", "046881", "026146", "053169", "005653", "093506", "016008", "030135", "115215", "067310", "019239", "038777", "112108", "094827", "058442", "108926", "081661", "010515", "001442", "067676", "008394", "128013", "062730", "048194", "125457", "128291", "034200", "099024", "103096", "044359", "066959", "048484", "063057", "126915", "093448", "126710", "096335", "119014", "019435", "091663", "001208", "002374", "027655", "058624", "030067", "029316", "105048", "048128", "073348", "095124", "093765", "003119", "011002", "016879", "067517", "007682", "005484", "060714", "017794", "077733", "000503", "122766", "052743", "098274", "053378", "090734", "039608", "061100", "109966", "091038", "076940", "015205", "108238", "124847", "048153", "100600", "120450", "002934", "086555", "035735", "054797", "119707", "049547", "054639", "019012", "019857", "013669", "116131", "030106", "016423", "005995", "067550", "056787", "128808", "068300", "041591", "090865", "026734", "060687", "045140", "027318", "099165", "062990", "067778", "088040", "052789", "078952", "069094", "070937", "021207", "082026", "005111", "121940", "033233", "110241", "087205", "120234", "028170", "082971", "035712", "110631", "049424", "033875", "022987", "008831", "126396", "058302", "061038", "091591", "084570", "002101", "024208", "099219", "079319", "041209", "069870", "116764", "112577", "005096", "042731", "033243", "003424", "033551", "013556", "043927", "042742", "068620", "020751", "102332", "128973", "083487", "115828", "119490", "131725", "022179", "028147", "122793", "071288", "105526", "075618", "052066", "046741", "095170", "053484", "008295", "049576", "010591", "060505", "052314", "126431", "093713", "054406", "099334", "055536", "063104", "031197", "003816", "104112", "104998", "116023", "007999", "012000", "022962", "055729", "119116", "131228", "005737", "020720", "047472", "100368", "132666", "069773", "094770", "052367", "000368", "109066", "118256", "103904", "124077", "094678", "069739", "088951", "024958", "045870", "105815", "118924", "093304", "115552", "065853", "128119", "005648", "126001", "053852", "052447", "038120", "118946", "036071", "014827", "067572", "112751", "025703", "089021", "079143", "078752", "084912", "097037", "076929", "104591", "007541", "100463", "125857", "010998", "073357", "038520", "060865", "025125", "042719", "041934", "002514", "030690", "012903", "117385", "034512", "067505", "004971", "036976", "113068", "023982", "021013", "021776", "009957", "104284", "004449", "116346", "123553", "017156", "016005", "124063", "018853", "074556", "117588", "077548", "005325", "027149", "041345", "103772", "068223", "119718", "092992", "085530", "098849", "069468", "008165", "022778", "051582", "018808", "107989", "024445", "124950", "025143", "051008", "025051", "016671", "099595", "031337", "004638", "019940", "058867", "030558", "087998", "107423", "121365", "119177", "009859", "117737", "060974", "026829", "005573", "029315", "038775", "078484", "029227", "056457", "086893", "122904", "031138", "113868", "063822", "108932", "006156", "016344", "005829", "037952", "032762", "115901", "018910", "061960", "098772", "078751", "105496", "133104", "047549", "009272", "098505", "109479", "077075", "074644", "002359", "026142", "003512", "056036", "040538", "068415", "097705", "027053", "122277", "039272", "023208", "096783", "027531", "123466", "016263", "131337", "090165", "089000", "093832", "037821", "024957", "091789", "055627", "004243", "003173", "096834", "117010", "083183", "106762", "016311", "106197", "026418", "043605", "007108", "064810", "052169", "002692", "022074", "071333", "067741", "054185", "022817", "129906", "118323", "097843", "123064", "006697", "128114", "080793", "108002", "105866", "025489", "084407", "105965", "069931", "012854", "022976", "013069", "008770", "092504", "087461", "024992", "057466", "088936", "026631", "107762", "080735", "053359", "010986", "003457", "044728", "054074", "099403", "030938", "073563", "024624", "100049", "044946", "058017", "069780", "072113", "105705", "018087", "062709", "094455", "035297", "104005", "046075", "073502", "101331", "071684", "071350", "038571", "051631", "011028", "090527", "121273", "034076", "102477", "093997", "057734", "077663", "057225", "069007", "008510", "121747", "004664", "087567", "122958", "001382", "094315", "064932", "094086", "125842", "006130", "086468", "057108", "116260", "061878", "112604", "037424", "035255", "078836", "060306", "001056", "034607", "024646", "072200", "075577", "065272", "000724", "083576", "073719", "088727", "026414", "115268", "031879", "097149", "068579", "024882", "049268", "023675", "064135", "102870", "005181", "024963", "128580", "025354", "004804", "040795", "102286", "016722", "024598", "072038", "022797", "036209", "132841", "073767", "064392", "028194", "072872", "117571", "026409", "084008", "085293", "006350", "010109", "011266", "079265", "114628", "025908", "063945", "034587", "084237", "051979", "085274", "033035", "094308", "007535", "128313", "031314", "095045", "046216", "001520", "019152", "053702", "018345", "070924", "084147", "133158", "119057", "103612", "103381", "027640", "077436", "105175", "103760", "024393", "005862", "096942", "007466", "030861", "122157", "095500", "014617", "029407", "022015", "083353", "055432", "053669", "014620", "087454", "004536", "042934", "036427", "004633", "080120", "105728", "123046", "028058", "013985", "076761", "044287", "071697", "020784", "093963", "060718", "121655", "115322", "098512", "093306", "132894", "044024", "067859", "120857", "073012", "125950", "008239", "072759", "111305", "079473", "088564", "019950", "065855", "049156", "065657", "113511", "099604", "005363", "013234", "045015", "112325", "084539", "085811", "059374", "102926", "032344", "122850", "110059", "116060", "040654", "104622", "108271", "092203", "097284", "090943", "047091", "110750", "052479", "010741", "000945", "099259", "088719", "022785", "052682", "008585", "011947", "000442", "034779", "122442", "009423", "004724", "043849", "035191", "131753", "070326", "081630", "049344", "091053", "092332", "031108", "001153", "098570", "014453", "081769", "085294", "005884", "091607", "030814", "085090", "122273", "043576", "086465", "060744", "023845", "107231", "045689", "048684", "121684", "033706", "081698", "111950", "095478", "017754", "124020", "079926", "002701", "049198", "122690", "120043", "022775", "022872", "070441", "043720", "107312", "027028", "103877", "003532", "016313", "043476", "119268", "101188", "049451", "033814", "024034", "117628", "008909", "030460", "117102", "095394", "103184", "030844", "113509", "012611", "119616", "011367", "046708", "097466", "048611", "129544", "081074", "078116", "075460", "098306", "083519", "053132", "009135", "128772", "091112", "016781", "089166", "017599", "107275", "098207", "107344", "051947", "007828", "062830", "089104", "079133", "123302", "114938", "121852", "022794", "024378", "067154", "113433", "014495", "072271", "109742", "041433", "076625", "019731", "127372", "114908", "121267", "089688", "054806", "050426", "119739", "055250", "034020", "066592", "015583", "066595", "075100", "081121", "058016", "012336", "063821", "003397", "043552", "029335", "133239", "124195", "109614", "031905", "097619", "101086", "089474", "024618", "085286", "036482", "088767", "131150", "048273", "087163", "014741", "083014", "122301", "133485", "103403", "027504", "084478", "053461", "065120", "070751", "067165" ]}
--------------------------------------------------------------------------------
/data/zinc250k_config.txt:
--------------------------------------------------------------------------------
1 | {'atom_list': [6, 7, 8, 9, 15, 16, 17, 35, 53, 0], 'freedom': 0, 'node_dim': 10, 'max_size': 38, 'bond_dim': 4}
--------------------------------------------------------------------------------
/framework.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hlzhang109/PyTorch-GraphNVP/eb6cabd1e5e39f84ffe92662ef5d667aa4e30db3/framework.png
--------------------------------------------------------------------------------
/graph_nvp/__init__.py:
--------------------------------------------------------------------------------
1 | #from . import nvp_model
--------------------------------------------------------------------------------
/graph_nvp/coupling.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | from graph_nvp.mlp import MLP
4 | from graph_nvp.rgcn import RGCN
5 | from utils.argparser import args
6 |
7 | def create_inv_masks(masks):
8 | inversed_masks = masks.clone()
9 | inversed_masks[inversed_masks > 0] = 2
10 | inversed_masks[inversed_masks == 0] = 1
11 | inversed_masks[inversed_masks == 2] = 0
12 | return inversed_masks
13 |
14 | class Rescale(nn.Module):
15 | def __init__(self):
16 | super(Rescale, self).__init__()
17 | self.weight = nn.Parameter(torch.zeros([1]))
18 |
19 | def forward(self, x):
20 | if torch.isnan(torch.exp(self.weight)).any():
21 | print(self.weight)
22 | raise RuntimeError('Rescale factor has NaN entries')
23 |
24 | x = self.weight.exp() * x
25 | return x
26 |
27 | class Coupling(nn.Module):
28 |
29 | def __init__(self, num_nodes, num_relations, num_features, mask,
30 | batch_norm=False):
31 | super(Coupling, self).__init__()
32 | self.num_nodes = num_nodes
33 | self.num_relations = num_relations
34 | self.num_bonds = num_relations
35 | self.num_features = num_features
36 |
37 | self.adj_size = self.num_nodes * self.num_nodes * self.num_relations
38 | self.x_size = self.num_nodes * self.num_features
39 | self.apply_batch_norm = batch_norm
40 | self.mask = mask.to(args.device)
41 | self.inversed_mask = create_inv_masks(self.mask).to(args.device)
42 |
43 | def forward(self, *args, **kwargs):
44 | raise NotImplementedError
45 |
46 | def reverse(self):
47 | raise NotImplementedError
48 |
49 |
50 | class AffineAdjCoupling(Coupling):
51 |
52 | def __init__(self, num_nodes, num_relations, num_features, mask,
53 | batch_norm=False, num_masked_cols=1,
54 | ch_list=None):
55 | super(AffineAdjCoupling, self).__init__(num_nodes, num_relations, num_features, mask,
56 | batch_norm=batch_norm)
57 | self.num_masked_cols = num_masked_cols
58 | self.ch_list = ch_list
59 | self.adj_size = num_nodes * num_nodes * num_relations
60 | self.out_size = num_nodes * num_relations
61 | self.in_size = self.adj_size - self.out_size
62 |
63 | self.mlp = MLP(ch_list, in_size=self.in_size)
64 | self.lin = nn.Linear(ch_list[-1], 2 * self.out_size)
65 | self.scale_factor = torch.zeros(1, device=args.device)
66 | self.batch_norm = nn.BatchNorm1d(self.in_size)
67 | self.tanh = nn.Tanh()
68 | self.sigmoid = nn.Sigmoid()
69 | self.rescale = Rescale()
70 |
71 | def forward(self, adj):
72 | masked_adj = adj[:, :, self.mask>0].to(args.device)
73 | log_s, t = self._s_t_functions(masked_adj)
74 | t = t.expand(adj.shape)
75 | s = self.sigmoid(log_s + 2)
76 | s = s.expand(adj.shape)
77 | log_det_jacobian = torch.sum(torch.log(torch.abs(s)), axis=(1, 2, 3))
78 | return adj, log_det_jacobian
79 |
80 | def reverse(self, adj):
81 | masked_adj = adj[:, :, self.mask>0].to(args.device)
82 | log_s, t = self._s_t_functions(masked_adj)
83 | t = t.expand(adj.shape)
84 | s = self.sigmoid(log_s + 2)
85 | s = s.expand(adj.shape)
86 | adj = adj * self.mask + (((adj - t)/s) * self.inversed_mask)
87 | return adj, None
88 |
89 | def _s_t_functions(self, adj):
90 | x = adj.view(adj.shape[0], -1).to(args.device)
91 | if self.apply_batch_norm:
92 | x = self.batch_norm(x)
93 | y = self.mlp(x)
94 | y = self.tanh(y)
95 | y = self.lin(y)
96 | y = self.rescale(y)
97 | s = y[:, :self.out_size]
98 | t = y[:, self.out_size:]
99 | s = s.view(y.shape[0], self.num_relations, self.num_nodes, 1).to(args.device)
100 | t = t.view(y.shape[0], self.num_relations, self.num_nodes, 1).to(args.device)
101 | return s, t
102 |
103 | class AffineNodeFeatureCoupling(Coupling):
104 |
105 | def __init__(self, num_nodes, num_bonds, num_features, mask,
106 | batch_norm=False, input_type='float',
107 | num_masked_cols=1, ch_list=None):
108 | super(AffineNodeFeatureCoupling, self).__init__(num_nodes, num_bonds,
109 | num_features, mask, batch_norm=batch_norm)
110 | self.num_masked_cols = num_masked_cols
111 | self.out_size = num_features * num_masked_cols
112 | self.rgcn = RGCN(num_features, nhid=128, nout=ch_list['hidden'][0], edge_dim=self.num_bonds,
113 | num_layers=args.num_gcn_layer, dropout=0., normalization=False).to(args.device)
114 | self.lin1 = nn.Linear(ch_list['hidden'][0], out_features=ch_list['hidden'][1])
115 | self.lin2 = nn.Linear(ch_list['hidden'][1], out_features=2*self.out_size)
116 | self.scale_factor = torch.zeros(1, device=args.device)
117 | self.batch_norm = nn.BatchNorm1d(ch_list['hidden'][0])
118 | self.tanh = nn.Tanh()
119 | self.sigmoid = nn.Sigmoid()
120 | self.rescale = Rescale()
121 |
122 | def forward(self, x, adj):
123 | masked_x = x * self.mask
124 | s, t = self._s_t_functions(masked_x, adj)
125 | x = masked_x + x * (s * self.inversed_mask) + t * self.inversed_mask
126 | log_det_jacobian = torch.sum(torch.log(torch.abs(s)), axis=(1, 2))
127 | return x, log_det_jacobian
128 |
129 | def reverse(self, y, adj):
130 | masked_y = y * self.mask
131 | s, t = self._s_t_functions(masked_y, adj)
132 | x = masked_y + (((y - t)/s) * self.inversed_mask)
133 | return x, None
134 |
135 | def _s_t_functions(self, x, adj):
136 | h = self.rgcn(x, adj)
137 | batch_size = x.shape[0]
138 | if self.apply_batch_norm:
139 | h = self.batch_norm(h)
140 | h = self.lin1(h)
141 | h = self.tanh(h)
142 | h = self.lin2(h)
143 | h = self.rescale(h)
144 | s = h[:, :self.out_size]
145 | t = h[:, self.out_size:]
146 | s = self.sigmoid(s + 2)
147 |
148 | t = t.view(batch_size, 1, self.out_size)
149 | t = t.expand(batch_size, int(self.num_nodes / self.num_masked_cols), self.out_size).to(args.device)
150 | s = s.view(batch_size, 1, self.out_size)
151 | s = s.expand(batch_size, int(self.num_nodes / self.num_masked_cols), self.out_size).to(args.device)
152 | return s, t
153 |
154 |
155 | class AdditiveAdjCoupling(Coupling):
156 |
157 | def __init__(self, num_nodes, num_relations, num_features, mask,
158 | batch_norm=False,
159 | num_masked_cols=1, ch_list=None):
160 | super(AdditiveAdjCoupling, self).__init__(num_nodes, num_relations,
161 | num_features, mask,
162 | batch_norm=batch_norm)
163 | self.num_masked_cols = num_masked_cols
164 | self.adj_size = num_nodes * num_nodes * num_relations
165 | self.out_size = num_nodes * num_relations
166 | self.in_size = self.adj_size - self.out_size
167 | self.mlp = MLP(ch_list, in_size=self.in_size)
168 | self.lin = nn.Linear(ch_list[-1], out_features=self.out_size)
169 | self.batch_norm = nn.BatchNorm1d(self.in_size)
170 | self.scale_factor = torch.zeros(1, device=args.device)
171 | self.tanh = nn.Tanh()
172 | self.rescale = Rescale()
173 |
174 | def forward(self, adj):
175 | masked_adj = adj[:, :, self.mask>0].to(args.device)
176 | t = self._s_t_functions(masked_adj)
177 | t = t.expand(adj.shape)
178 | adj = adj + t * self.inversed_mask
179 | return adj, torch.zeros(1, device=args.device)
180 |
181 | def reverse(self, adj):
182 | masked_adj = adj[:, :, self.mask>0].to(args.device)
183 | t = self._s_t_functions(masked_adj)
184 | t = t.expand(adj.shape)
185 | adj = adj - t * self.inversed_mask
186 | return adj, None
187 |
188 | def _s_t_functions(self, adj):
189 | adj = adj.view(adj.shape[0], -1)
190 | x = adj.clone()
191 | if self.apply_batch_norm:
192 | x = self.batch_norm(x)
193 | y = self.mlp(x)
194 | y = self.tanh(y)
195 | y = self.lin(y)
196 | y = self.rescale(y)
197 | y = y.view(y.shape[0], self.num_relations, self.num_nodes, 1)
198 | return y
199 |
200 | class AdditiveNodeFeatureCoupling(Coupling):
201 | def __init__(self, num_nodes, num_bonds, num_features,
202 | mask,
203 | batch_norm=False, ch_list=None,
204 | input_type='float', num_masked_cols=1):
205 | super(AdditiveNodeFeatureCoupling, self).__init__(num_nodes, num_bonds,
206 | num_features, mask,
207 | batch_norm=batch_norm)
208 | self.num_masked_cols = num_masked_cols
209 | self.out_size = num_features * num_masked_cols
210 | self.rgcn = RGCN(num_features, nhid=128, nout=ch_list['hidden'][0], edge_dim=self.num_bonds,
211 | num_layers=args.num_gcn_layer, dropout=0., normalization=False).to(args.device)
212 | self.lin1 = nn.Linear(ch_list['hidden'][0], out_features=ch_list['hidden'][1])
213 | self.lin2 = nn.Linear(ch_list['hidden'][1], out_features=self.out_size)
214 | self.scale_factor = torch.zeros(1, device=args.device)
215 | self.batch_norm = nn.BatchNorm1d(ch_list['hidden'][0])
216 | self.tanh = nn.Tanh()
217 | self.rescale = Rescale()
218 |
219 | def forward(self, x, adj):
220 | masked_x = x * self.mask
221 | batch_size = x.shape[0]
222 | t = self._s_t_functions(masked_x, adj)
223 | t = t.view(batch_size, 1, self.out_size)
224 | t = t.expand(batch_size, int(self.num_nodes/self.num_masked_cols), self.out_size)
225 | if self.num_masked_cols > 1:
226 | t = t.view(batch_size, self.num_nodes, self.num_features)
227 | x = x + t * self.inversed_mask
228 | return x, torch.zeros(1, device=args.device)
229 |
230 | def reverse(self, y, adj):
231 | masked_y = y * self.mask
232 | batch_size = y.shape[0]
233 | t = self._s_t_functions(masked_y, adj)
234 | t = t.view(batch_size, 1, self.out_size)
235 | t = t.expand(batch_size, int(self.num_nodes/self.num_masked_cols), self.out_size)
236 | if self.num_masked_cols > 1:
237 | t = t.view(batch_size, self.num_nodes, self.num_features)
238 | y = y - t * self.inversed_mask
239 | return y, None
240 |
241 | def _s_t_functions(self, x, adj):
242 | h = self.rgcn(x, adj)
243 | if self.apply_batch_norm:
244 | h = self.batch_norm(h)
245 | h = self.lin1(h)
246 | h = self.tanh(h)
247 | h = self.lin2(h)
248 | h = self.rescale(h)
249 | return h
250 |
--------------------------------------------------------------------------------
/graph_nvp/hyperparams.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | import numpy as np
5 | from tabulate import tabulate
6 |
7 |
8 | class Hyperparameters:
9 | def __init__(self, num_nodes=-1, num_relations=-1, num_features=-1, masks=None, path=None,
10 | num_masks=None, mask_size=None, num_coupling=None, batch_norm=False,
11 | additive_transformations=False, learn_dist=True,
12 | squeeze_adj=False, prior_adj_var=1.0, prior_x_var=1.0,
13 | mlp_channels=None, gnn_channels=None, seed=1):
14 | self.gnn_channels = gnn_channels
15 | self.mlp_channels = mlp_channels
16 | self.num_nodes = num_nodes
17 | self.num_relations = num_relations
18 | self.num_features = num_features
19 | self.masks = masks
20 | self.num_masks = num_masks
21 | self.mask_size = mask_size
22 | self.num_coupling = num_coupling
23 | self.path = path
24 | self.apply_batch_norm = batch_norm
25 | self.additive_transformations = additive_transformations
26 | self.learn_dist = learn_dist
27 | self.squeeze_adj = squeeze_adj
28 | self.prior_adj_var = prior_adj_var
29 | self.prior_x_var = prior_x_var
30 | self.seed = seed
31 |
32 | if path is not None:
33 | if os.path.exists(path) and os.path.isfile(path):
34 | with open(path, "r") as f:
35 | obj = json.load(f)
36 | for (key, value) in obj.items():
37 | if key == 'masks':
38 | masks = dict()
39 | for k in value.keys():
40 | if value[k]:
41 | dtype = np.bool
42 | masks[k] = [np.array(item, dtype=np.bool) for item in value[k]]
43 | value = masks
44 | setattr(self, key, value)
45 | else:
46 | raise Exception("{} does not exist".format(path))
47 |
48 | def save(self, path):
49 | self.path = path
50 | with open(path, "w") as f:
51 | json.dump(self.__dict__, f, indent=4, sort_keys=True, cls=NumpyEncoder)
52 |
53 | def print(self):
54 | rows = []
55 | for key, value in self.__dict__.items():
56 | rows.append([key, value])
57 | print(tabulate(rows))
58 |
59 |
60 | class NumpyEncoder(json.JSONEncoder):
61 | def default(self, obj):
62 | if isinstance(obj, np.ndarray):
63 | return obj.tolist()
64 | return json.JSONEncoder.default(self, obj)
65 |
66 |
--------------------------------------------------------------------------------
/graph_nvp/mlp.py:
--------------------------------------------------------------------------------
1 | import torch.nn as nn
2 |
3 | class MLP(nn.Module):
4 | def __init__(self, units, in_size=None):
5 | super(MLP, self).__init__()
6 | assert isinstance(units, (tuple, list))
7 | assert len(units) >= 1
8 | n_layers = len(units)
9 |
10 | units_list = [in_size] + list(units)
11 | layers = []
12 | for i in range(n_layers):
13 | layers.append(nn.Linear(units_list[i], units_list[i+1]))
14 | self.layers = nn.Sequential(*layers)
15 | self.n_layers = n_layers
16 |
17 | def forward(self, x):
18 | output = self.layers(x)
19 | return output
20 |
--------------------------------------------------------------------------------
/graph_nvp/nvp_model.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | import torch.nn.functional as F
4 | import numpy as np
5 | from utils.argparser import args
6 | from graph_nvp.hyperparams import Hyperparameters
7 | from graph_nvp.coupling import AffineNodeFeatureCoupling, AffineAdjCoupling, \
8 | AdditiveNodeFeatureCoupling, AdditiveAdjCoupling
9 |
10 | def gaussian_nll(x, mean, ln_var, reduce='sum'):
11 | if reduce not in ('sum', 'mean', 'no'):
12 | raise ValueError(
13 | 'only \'sum\', \'mean\' and \'no\' are valid for \'reduce\', but '
14 | '\'%s\' is given' % reduce)
15 |
16 | x_prec = torch.exp(-ln_var)
17 | x_diff = x - mean
18 | x_power = (x_diff * x_diff) * x_prec * -0.5
19 | loss = (ln_var + torch.log(torch.tensor([2 * np.pi], device=args.device, dtype=torch.float32))) / 2 - x_power
20 | if reduce == 'sum':
21 | return torch.sum(loss)
22 | elif reduce == 'mean':
23 | return torch.mean(loss)
24 | else:
25 | return loss
26 |
27 | class GraphNvpModel(nn.Module):
28 | def __init__(self, hyperparams: Hyperparameters):
29 | super(GraphNvpModel, self).__init__()
30 | self.hyperparams = hyperparams
31 | self._init_params(hyperparams)
32 | self._need_initialization = False
33 | if self.masks is None:
34 | self._need_initialization = True
35 | self.masks = dict()
36 | self.masks['node'] = self._create_masks('node')
37 | self.masks['channel'] = self._create_masks('channel')
38 | self.num_bonds = self.num_relations
39 | self.num_atoms = self.num_nodes
40 | assert self.num_bonds+1 == self.num_features
41 | self.adj_size = self.num_atoms * self.num_atoms * self.num_relations
42 | self.x_size = self.num_atoms * self.num_features
43 | #self.prior_ln_var = torch.tensor([0.7],device=args.device, dtype=torch.float32)
44 | self.prior_ln_var = nn.Parameter(torch.zeros([1]))
45 | nn.init.constant_(self.prior_ln_var, 1e-5)
46 | self.constant_pi = torch.tensor([3.1415926535], device=args.device, dtype=torch.float32)
47 | # AffineNodeFeatureCoupling found to be unstable.
48 | channel_coupling = AffineNodeFeatureCoupling
49 | node_coupling = AffineAdjCoupling
50 | if self.additive_transformations:
51 | channel_coupling = AdditiveNodeFeatureCoupling
52 | node_coupling = AdditiveAdjCoupling
53 | print("Additive Transformations")
54 | transforms = []
55 | for i in range(self.num_coupling['channel']):
56 | transforms += [channel_coupling(self.num_nodes, self.num_relations, self.num_features,
57 | self.masks['channel'][i % self.num_masks['channel']],
58 | num_masked_cols=int(self.num_nodes / self.num_masks['channel']),
59 | ch_list=self.gnn_channels,
60 | batch_norm=self.apply_batch_norm)]
61 | for i in range(self.num_coupling['node']):
62 | transforms += [node_coupling(self.num_nodes, self.num_relations, self.num_features,
63 | self.masks['node'][i % self.num_masks['node']],
64 | num_masked_cols=int(self.num_nodes / self.num_masks['channel']),
65 | batch_norm=self.apply_batch_norm,
66 | ch_list=self.mlp_channels)]
67 | self.transforms = nn.ModuleList(transforms)
68 |
69 | def forward(self, adj, x):
70 | h = x.clone()
71 | sum_log_det_jacs_x = torch.zeros(h.shape[0], device=args.device, requires_grad=True)
72 | sum_log_det_jacs_adj = torch.zeros(h.shape[0], device=args.device, requires_grad=True)
73 | # forward step of channel-coupling layers
74 | for i in range(self.num_coupling['channel']):
75 | h, log_det_jacobians = self.transforms[i](h, adj)
76 | sum_log_det_jacs_x = sum_log_det_jacs_x + log_det_jacobians
77 | #adj = adj + 0.9 * torch.rand(adj.shape, device=args.device)
78 | for i in range(self.num_coupling['channel'], len(self.transforms)):
79 | adj, log_det_jacobians = self.transforms[i](adj)
80 | sum_log_det_jacs_adj = sum_log_det_jacs_adj + log_det_jacobians
81 |
82 | adj = adj.view(adj.shape[0], -1)
83 | h = h.view(h.shape[0], -1)
84 | out = [h, adj]
85 | return out, [sum_log_det_jacs_x, sum_log_det_jacs_adj]
86 |
87 | def reverse(self, z, x_size, true_adj=None):
88 | """
89 | Returns a molecule, given its latent vector.
90 | :param z: latent vector. Shape: [B, N*N*M + N*T]
91 | B = Batch size, N = number of atoms, M = number of bond types,
92 | T = number of atom types (Carbon, Oxygen etc.)
93 | :param true_adj: used for testing. An adjacency matrix of a real molecule
94 | :return: adjacency matrix and feature matrix of a molecule
95 | """
96 | # NOTE z is a list
97 | batch_size = z.shape[0]
98 | z_x = z[:, :x_size]
99 | z_adj = z[:, x_size:]
100 | temperature = 1.0
101 | if true_adj is None:
102 | h_adj = z_adj.view(batch_size, self.num_relations, self.num_nodes, self.num_nodes)
103 | # First, the adjacency coupling layers are applied in reverse order to get h_adj
104 | for i in reversed(range(self.num_coupling['channel'], len(self.transforms))):
105 | h_adj, log_det_jacobians = self.transforms[i].reverse(h_adj)
106 | adj = h_adj
107 | adj = adj + adj.permute(0, 1, 3, 2)
108 | adj = adj / 2.0
109 | adj = F.softmax(adj, dim=1)
110 | else:
111 | adj = true_adj
112 |
113 | h_x = z_x.view(batch_size, self.num_nodes, self.num_features)
114 | # channel coupling layers
115 | for i in reversed(range(self.num_coupling['channel'])):
116 | h_x, log_det_jacobians = self.transforms[i].reverse(h_x, adj)
117 | return adj, h_x
118 |
119 | def _init_params(self, hyperparams):
120 | self.num_nodes = hyperparams.num_nodes
121 | self.num_relations = hyperparams.num_relations
122 | self.num_features = hyperparams.num_features
123 | self.masks = hyperparams.masks
124 |
125 | self.apply_batch_norm = args.apply_batch_norm
126 | self.additive_transformations = args.additive_transformations
127 |
128 | self.num_masks = hyperparams.num_masks
129 | self.num_coupling = hyperparams.num_coupling
130 | self.mask_size = hyperparams.mask_size
131 | self.mlp_channels = hyperparams.mlp_channels
132 | self.gnn_channels = hyperparams.gnn_channels
133 |
134 | def _create_masks(self, type):
135 | masks = []
136 | num_cols = int(self.num_nodes / self.hyperparams.num_masks[type])
137 | if type == 'node':
138 | # Columns of the adjacency matrix is masked
139 | for i in range(self.hyperparams.num_masks[type]):
140 | node_mask = torch.ones([self.num_nodes, self.num_nodes])
141 | for j in range(num_cols):
142 | node_mask[:, i + j] = 0.0
143 | masks.append(node_mask)
144 | elif type == 'channel':
145 | # One row (one node) of the feature matrix is masked
146 | num_cols = int(self.num_nodes / self.hyperparams.num_masks[type])
147 | for i in range(self.hyperparams.num_masks[type]):
148 | ch_mask = torch.ones([self.num_nodes, self.num_features])
149 | for j in range(num_cols):
150 | ch_mask[i * num_cols + j, :] = 0.0
151 | masks.append(ch_mask)
152 | return masks
153 |
154 | def log_prob(self, z, logdet):
155 | # z = [h, adj], logdet: [sum_log_det_jacs_x, sum_log_det_jacs_adj]
156 | logdet[0] = logdet[0] - self.x_size
157 | logdet[1] = logdet[1] - self.adj_size
158 |
159 | ll_node = -1 / 2 * (torch.log(2 * self.constant_pi) + self.prior_ln_var + torch.exp(-self.prior_ln_var) * (z[0] ** 2))
160 | ll_node = ll_node.sum(-1) # (B)
161 |
162 | ll_edge = -1 / 2 * (torch.log(2 * self.constant_pi) + self.prior_ln_var + torch.exp(-self.prior_ln_var) * (z[1] ** 2))
163 | ll_edge = ll_edge.sum(-1) # (B)
164 |
165 | ll_node += logdet[0] # ([B])
166 | ll_edge += logdet[1] # ([B])
167 |
168 | nll = -(ll_node.mean() / self.x_size + ll_edge.mean() / self.adj_size) / 2.0
169 | return nll
170 |
171 | def save_hyperparams(self, path):
172 | self.hyperparams.save(path)
173 |
174 | def load_hyperparams(self, path):
175 | """
176 | loads hyper parameters from a json file
177 | :param path:
178 | :return:
179 | """
180 | hyperparams = Hyperparameters(path=path)
181 | self._init_params(hyperparams)
182 |
183 |
--------------------------------------------------------------------------------
/graph_nvp/rgcn.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | import torch.nn.functional as F
4 | from utils.argparser import args
5 |
6 | def Linear(in_features, out_features, bias=True):
7 | m = nn.Linear(in_features, out_features, bias)
8 | nn.init.xavier_uniform_(m.weight)
9 | if bias:
10 | nn.init.constant_(m.bias, 0.0)
11 | return m
12 |
13 | class Switch(nn.Module):
14 | def __init__(self):
15 | super(Switch, self).__init__()
16 | def forward(self, x):
17 | return x * torch.sigmoid(x)
18 |
19 | class RelationGraphConvolution(nn.Module):
20 | """
21 | Relation GCN layer.
22 | """
23 | def __init__(self, in_features, out_features, edge_dim=3, aggregate='sum', dropout=0., use_relu=True, bias=False):
24 | '''
25 | :param in/out_features: scalar of channels for node embedding
26 | :param edge_dim: dim of edge type, virtual type not included
27 | '''
28 | super(RelationGraphConvolution, self).__init__()
29 | self.in_features = in_features
30 | self.out_features = out_features
31 | self.edge_dim = edge_dim
32 | self.dropout = dropout
33 | self.aggregate = aggregate
34 | if use_relu:
35 | self.act = nn.ReLU()
36 | elif args.use_switch:
37 | self.act = Switch()
38 | else:
39 | self.act = None
40 |
41 | self.weight = nn.Parameter(torch.FloatTensor(
42 | self.edge_dim, self.in_features, self.out_features))
43 | if bias:
44 | self.bias = nn.Parameter(torch.FloatTensor(
45 | self.edge_dim, 1, self.out_features))
46 | else:
47 | self.register_parameter('bias', None)
48 | self.reset_parameters()
49 | self.graph_linear_self = GraphLinear(in_features, out_features)
50 | self.graph_linear_edge = GraphLinear(in_features, out_features * edge_dim)
51 |
52 | def reset_parameters(self):
53 | nn.init.xavier_uniform_(self.weight)
54 | if self.bias is not None:
55 | nn.init.constant_(self.bias, 0.)
56 |
57 | def forward(self, x, adj):
58 | '''
59 | :param x: (batch, N, d)
60 | :param adj: (batch, E, N, N)
61 | typically d=9 e=3
62 | :return:
63 | updated x with shape (batch, N, d)
64 | '''
65 | x = F.dropout(x, p=self.dropout, training=self.training) # (b, N, d)
66 |
67 | batch_size = x.size(0)
68 |
69 | mb, node, ch = x.shape
70 |
71 | # --- self connection, apply linear function ---
72 | hs = self.graph_linear_self(x)
73 | # --- relational feature, from neighbor connection ---
74 | # Expected number of neighbors of a vertex
75 | # Since you have to divide by it, if its 0, you need to arbitrarily set it to 1
76 | m = self.graph_linear_edge(x)
77 | m = m.view(mb, node, self.out_features, self.edge_dim)
78 | m = m.permute(0, 3, 1, 2)
79 | # m: (batchsize, edge_type, node, ch)
80 | # hr: (batchsize, edge_type, node, ch)
81 | hr = torch.matmul(adj, m)
82 | # hr: (batchsize, node, ch)
83 | hr = torch.sum(hr, 1)#dim=1)
84 | return hs + hr
85 |
86 |
87 | def __repr__(self):
88 | return self.__class__.__name__ + ' (' + str(self.in_features) + ' -> ' + str(self.out_features) + ')'
89 |
90 | def _get_embs_node(self, x, adj):
91 | """
92 | Args:
93 | x: current node feature matrix with shape (batch, N, 9)
94 | adj: current adjacency feature matrix with shape (batch, 4, N, N)
95 | Returns:
96 | graph embedding for updating node features with shape (batch, d)
97 | """
98 |
99 | batch_size = x.size(0)
100 | adj = adj[:, :3] # (batch, 3, N, N)
101 |
102 | node_emb = self.rgcn(x, adj) # (batch, N, d)
103 | if self.is_batchNorm:
104 | node_emb = self.batchNorm(node_emb.transpose(1, 2)).transpose(1, 2) # (batch, N, d)
105 |
106 | graph_emb = torch.sum(node_emb, dim=1, keepdim=False).contiguous() # (batch, d)
107 | return graph_emb
108 |
109 |
110 | class GraphAggregation(nn.Module):
111 |
112 | def __init__(self, in_features=128, out_features=64, b_dim=4, dropout=0.):
113 | super(GraphAggregation, self).__init__() #+b_dim
114 | self.sigmoid_linear = nn.Sequential(nn.Linear(in_features, out_features),
115 | nn.Sigmoid()) #+b_dim
116 | self.tanh_linear = nn.Sequential(nn.Linear(in_features, out_features),
117 | nn.Tanh())
118 | self.dropout = nn.Dropout(dropout)
119 | self.switch = Switch()
120 |
121 | def forward(self, input, activation):
122 | i = self.sigmoid_linear(input)
123 | j = self.tanh_linear(input)
124 | output = torch.sum(torch.mul(i,j), 1)
125 | if args.use_switch:
126 | output = self.switch(output)
127 | else:
128 | output = activation(output) if activation is not None\
129 | else output
130 | output = self.dropout(output)
131 | return output
132 |
133 | class GraphLinear(nn.Module):
134 | """Graph Linear layer.
135 |
136 | This function assumes its input is 3-dimensional.
137 | Differently from :class:`chainer.functions.linear`, it applies an affine
138 | transformation to the third axis of input `x`.
139 |
140 | .. seealso:: :class:`torch.nn.Linear`
141 | """
142 | def __init__(self, *argv, **kwargs):
143 | super(GraphLinear, self).__init__()
144 | #self.linear = spectral_norm(nn.Linear(*argv, **kwargs))
145 | self.linear = nn.Linear(*argv, **kwargs)
146 |
147 | def __call__(self, x):
148 | """Forward propagation.
149 | Args:
150 | x (:class:`torch.Tensor`)
151 | Input array that should be a float array whose ``dim`` is 3.
152 | Returns:
153 | :class:`torch.Tensor`:
154 | A 3-dimeisional array.
155 | """
156 | # (minibatch, atom, ch)
157 | s0, s1, s2 = x.size()
158 | x = x.view(s0 * s1, s2)
159 | x = self.linear(x)
160 | x = x.view(s0, s1, -1)
161 | return x
162 |
163 | class RGCN(nn.Module):
164 | def __init__(self, nfeat, nhid=256, nout=128, aggout=64, edge_dim=3, num_layers=3, dropout=0., normalization=False):
165 | '''
166 | :num_layars: the number of layers in each R-GCN
167 | '''
168 | super(RGCN, self).__init__()
169 |
170 | self.nfeat = nfeat
171 | self.nhid = nhid
172 | self.nout = nout
173 | self.edge_dim = edge_dim
174 | self.num_layers = num_layers
175 |
176 | self.dropout = dropout
177 | self.emb = Linear(nfeat, nfeat, bias=False)
178 |
179 | self.gc1 = RelationGraphConvolution(
180 | nfeat, nhid, edge_dim=self.edge_dim, aggregate='sum', use_relu=True, dropout=self.dropout, bias=False)
181 | self.gc2 = nn.ModuleList([RelationGraphConvolution(nhid, nhid, edge_dim=self.edge_dim, aggregate='sum',
182 | use_relu=True, dropout=self.dropout, bias=False)
183 | for i in range(self.num_layers-2)])
184 | self.gc3 = RelationGraphConvolution(
185 | nhid, nout, edge_dim=self.edge_dim, aggregate='sum', use_relu=False, dropout=self.dropout, bias=False)
186 |
187 | self.agg = GraphAggregation(nout, aggout, b_dim=edge_dim, dropout=dropout)
188 | self.output_layer = nn.Linear(aggout, 1)
189 |
190 | def forward(self, x, adj):
191 | '''
192 | :param x: (batch, N, d)
193 | :param adj: (batch, E, N, N)
194 | :return:
195 | '''
196 | # TODO: Add normalization for adacency matrix
197 | x = self.emb(x)
198 | x = self.gc1(x, adj)
199 | for i in range(self.num_layers-2):
200 | x = self.gc2[i](x, adj) # (#node, #class)
201 | x = self.gc3(x, adj) # (batch, N, d)
202 | #graph_emb = torch.sum(x, dim=1, keepdim=False).contiguous()
203 | x = self.agg(x, torch.tanh) # [256,64]
204 | return x
205 |
206 | def _get_embs_node(self, x, adj):
207 | """
208 | Args:
209 | x: current node feature matrix with shape (batch, N, 9)
210 | adj: current adjacency feature matrix with shape (batch, 4, N, N)
211 | Returns:
212 | graph embedding for updating node features with shape (batch, d)
213 | """
214 | batch_size = x.size(0)
215 | adj = adj[:, :3] # (batch, 3, N, N)
216 |
217 | node_emb = self.rgcn(x, adj) # (batch, N, d)
218 | if self.is_batchNorm:
219 | node_emb = self.batchNorm(node_emb.transpose(1, 2)).transpose(1, 2) # (batch, N, d)
220 |
221 | graph_emb = torch.sum(node_emb, dim=1, keepdim=False).contiguous() # (batch, d)
222 | return graph_emb
--------------------------------------------------------------------------------
/train.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | CUDA_VISIBLE_DEVICES=1 python train_mle.py --batch_size 256 \
3 | --data_file qm9_relgcn_kekulized_ggnp.npz \
4 | --epochs 10 \
5 | --device cuda \
6 | --num_node_masks 9 \
7 | --num_channel_masks 9 \
8 | --num_node_coupling 18 \
9 | --num_channel_coupling 14 \
10 | --additive_transformations True \
11 | --apply_batch_norm True \
12 | --node_mask_size 15 \
13 | --mode train \
14 | --num_gen 100 \
15 | --show_loss_step 5 \
16 | --gen_path ./results/qm9_mols \
17 | --model_save_dir ./saved_qm9_models \
18 | --img_dir=./results/qm9_img
19 |
--------------------------------------------------------------------------------
/train_mle.py:
--------------------------------------------------------------------------------
1 | from time import time
2 | from utils.argparser import args
3 | import os, sys, copy
4 | import math
5 | import copy
6 | import random
7 | import numpy as np
8 | import torch
9 | import torch.nn.functional as F
10 | from os.path import join as joinpath
11 | from rdkit import Chem
12 | import chainer
13 | from chainer.datasets import TransformDataset
14 | from chainer.dataset import iterator as iterator_module, convert
15 | from chainer_chemistry.datasets import NumpyTupleDataset
16 | from graph_nvp.hyperparams import Hyperparameters
17 | from graph_nvp.nvp_model import GraphNvpModel
18 | from utils import environment as env
19 | from utils.data_utils import construct_mol, save_mol_png
20 | from tqdm import tqdm
21 |
22 | def read_molecules(path):
23 | f = open(joinpath(path, '{}_config.txt'.format(args.data_name)), 'r')
24 | data_config = eval(f.read())
25 | f.close()
26 | fp = open(joinpath(args.data_dir, '{}_kekulized_ggnp.txt'.format(args.data_name)), 'r')
27 | all_smiles = [smiles.strip() for smiles in fp]
28 | fp.close()
29 | return data_config, all_smiles
30 |
31 | def sample_z(model, batch_size=args.batch_size, z_mu=None):
32 | z_dim = model.adj_size + model.x_size
33 | mu = np.zeros([z_dim], dtype=np.float32)
34 | sigma_diag = np.ones([z_dim])
35 | sigma_diag = np.sqrt(np.exp(model.prior_ln_var.item())) * sigma_diag
36 | sigma = args.temp * sigma_diag
37 |
38 | if z_mu is not None:
39 | mu = z_mu
40 | sigma = 0.01 * np.eye(z_dim, dtype=np.float32)
41 |
42 | z = np.random.normal(mu, sigma, (batch_size, z_dim)).astype(np.float32)
43 | z = torch.from_numpy(z).float().to(args.device)
44 | return z.detach()
45 |
46 | def main():
47 | args.cuda = torch.cuda.is_available()
48 | args.device = 'cuda' if torch.cuda.is_available() else 'cpu'
49 | print(args)
50 | if args.data_name == 'qm9':
51 | from data import transform_qm9
52 | transform_fn = transform_qm9.transform_fn
53 | args.atomic_num_list = [6, 7, 8, 9, 0]
54 | mlp_channels = [256, 256]
55 | gnn_channels = {'gcn': [8, 64], 'hidden': [64, 128]}
56 | valid_idx = transform_qm9.get_val_ids()
57 | elif args.data_name == 'zinc250k':
58 | from data import transform_zinc250k
59 | from data.transform_zinc250k import transform_fn_zinc250k
60 | transform_fn = transform_fn_zinc250k
61 | args.atomic_num_list = [6, 7, 8, 9, 15, 16, 17, 35, 53, 0]
62 | mlp_channels = [1024, 512]
63 | gnn_channels = {'gcn': [16, 128], 'hidden': [64, 256]}
64 | valid_idx = transform_zinc250k.get_val_ids()
65 |
66 | dataset = NumpyTupleDataset.load(joinpath(args.data_dir, args.data_file))
67 | dataset = TransformDataset(dataset, transform_fn)
68 |
69 | if len(valid_idx) > 0:
70 | train_idx = [t for t in range(len(dataset)) if t not in valid_idx]
71 | n_train = len(train_idx)
72 | train_idx.extend(valid_idx)
73 | train, test = chainer.datasets.split_dataset(dataset, n_train, train_idx)
74 | else:
75 | train, test = chainer.datasets.split_dataset_random(dataset, int(len(dataset) * 0.8), seed=args.seed)
76 |
77 | num_masks = {'node': args.num_node_masks, 'channel': args.num_channel_masks}
78 | mask_size = {'node': args.node_mask_size, 'channel': args.channel_mask_size}
79 | num_coupling = {'node': args.num_node_coupling, 'channel': args.num_channel_coupling}
80 | NVPmodel_params = Hyperparameters(args.num_atoms, args.num_rels, len(args.atomic_num_list),
81 | num_masks=num_masks, mask_size=mask_size, num_coupling=num_coupling,
82 | batch_norm=args.apply_batch_norm,
83 | additive_transformations=args.additive_transformations,
84 | mlp_channels=mlp_channels,
85 | gnn_channels=gnn_channels)
86 | model = GraphNvpModel(NVPmodel_params).to(args.device)
87 | train_iter = chainer.iterators.SerialIterator(train, args.batch_size, repeat=False)
88 |
89 | if isinstance(train_iter, iterator_module.Iterator):
90 | iterator = {'main': train_iter}
91 | # train_dataloader
92 | dataloader = iterator['main']
93 | data_config, all_train_smiles = read_molecules(args.data_dir)
94 | converter = convert.concat_examples
95 |
96 | # fitting
97 | t_total = time()
98 | total_g_loss, total_d_loss = [], []
99 | max_size = model.num_atoms # 9 for QM9
100 | num_atom = max_size
101 | node_dim = model.num_features # 5 for QM9 # OR exclude padding dim. 5-1
102 | bond_dim = model.num_bonds # 4 for QM9
103 | best_g_loss, best_d_loss = sys.maxsize, sys.maxsize
104 | start_epoch = args.resume_epoch
105 | if args.resume:
106 | model = GraphNvpModel(hyperparams=NVPmodel_params).to(args.device)
107 | model_path = joinpath(args.model_save_dir, 'epoch{}-mle.ckpt'.format(args.resume_epoch))
108 | model.load_state_dict(torch.load(model_path, map_location=lambda storage, loc: storage))
109 | print("Resuming from epoch{}".format(args.resume_epoch))
110 |
111 | all_unique_rate = []
112 | all_valid_rate = []
113 | all_novelty_rate = []
114 | print('start fitting.')
115 |
116 | optimizer = torch.optim.Adam(filter(lambda p: p.requires_grad, model.parameters()), args.mle_lr, betas=(args.beta1, args.beta2))
117 | scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min',
118 | factor=args.lr_decay_factor,
119 | patience=args.lr_decay_patience,
120 | min_lr=args.lr_decay_min)
121 | optimizer.step()
122 |
123 | def generate_one(model, mute=False, cnt=None):
124 | """
125 | inverse flow to generate one molecule
126 | Args:
127 | temp: temperature of normal distributions, we sample from (0, temp^2 * I)
128 | """
129 | generate_start_t = time()
130 | num2bond = {0: Chem.rdchem.BondType.SINGLE, 1: Chem.rdchem.BondType.DOUBLE, 2: Chem.rdchem.BondType.TRIPLE}
131 | num2bond_symbol = {0: '=', 1: '==', 2: '==='}
132 | num2atom = {0: 6, 1: 7, 2: 8, 3: 9, 4: 15, 5: 16, 6: 17, 7: 35, 8: 53}
133 | num2symbol = {0: 'C', 1: 'N', 2: 'O', 3: 'F', 4: 'P', 5: 'S', 6: 'Cl', 7: 'Br', 8: 'I'}
134 | is_continue = True
135 | mol = None
136 | total_resample = 0
137 | batch_size = 1
138 | # Generating
139 | z = sample_z(model, batch_size=1)
140 | A, X = model.reverse(z, model.x_size) # For QM9: [16,9,9,5], [16,9,5], [16,8]-[B,z_dim]
141 | X = F.softmax(X, dim=2)
142 | mols = [construct_mol(x_elem, adj_elem, args.atomic_num_list)
143 | for x_elem, adj_elem in zip(X, A)]
144 | pure_valid = 0
145 | smiles = ''
146 | num_atoms = -1
147 | for mol in mols:
148 | assert mol is not None, 'mol is None...'
149 | final_valid = env.check_chemical_validity(mol)
150 | valency_valid = env.check_valency(mol)
151 |
152 | if final_valid is False or valency_valid is False:
153 | print('Warning: use valency check during generation but the final molecule is invalid!!!')
154 | continue
155 | num_atoms = mol.GetNumAtoms()
156 | num_bonds = mol.GetNumBonds()
157 | smiles = Chem.MolToSmiles(mol)
158 |
159 | if total_resample == 0:
160 | pure_valid = 1.0
161 | if not mute:
162 | cnt = str(cnt) if cnt is not None else ''
163 | print('smiles%s: %s | #atoms: %d | #bonds: %d | #resample: %.5f | time: %.5f |' % (
164 | cnt, smiles, num_atoms, num_bonds, total_resample, time() - generate_start_t))
165 | return smiles, A, X, pure_valid, num_atoms
166 |
167 | def train(model):
168 | for epoch in range(1+start_epoch, args.epochs + 1 - start_epoch):
169 | batch_g_losses = []
170 | batch_cnt = 0
171 | epoch_example = 0
172 | num_samples = len(dataloader.dataset)
173 | num_batches = math.ceil(num_samples / args.batch_size)
174 | pbar = tqdm(total=num_batches)
175 |
176 | for i_batch, batch_data in enumerate(copy.copy(dataloader)):
177 | batch_time_s = time()
178 | loss = {}
179 | in_arrays = converter(batch_data)
180 | X, A, label = in_arrays[0], in_arrays[1], in_arrays[2]
181 | X, A, label = torch.tensor(X, dtype=torch.float32).to(args.device), \
182 | torch.tensor(A, dtype=torch.float32).to(args.device), \
183 | torch.tensor(label, dtype=torch.float32).to(args.device)
184 | # Dequantization
185 | X_prime = X + 0.9 * torch.rand(X.shape, device=args.device)
186 | A_prime = A + 0.9 * torch.rand(A.shape, device=args.device)
187 | z, sum_log_det_jacs = model(A_prime, X_prime)
188 | nll = model.log_prob(z, sum_log_det_jacs)
189 | g_loss = nll
190 | loss['G/loss_g'] = g_loss.item()
191 | batch_g_losses.append(g_loss.item())
192 | optimizer.zero_grad()
193 | g_loss.backward()
194 | optimizer.step()
195 | scheduler.step(g_loss)
196 | pbar.update()
197 | if i_batch % args.show_loss_step == 0:
198 | tqdm.write("Epoch %d, batch %d, Loss mle: %.5f" % (epoch, i_batch, g_loss.item()))
199 | pbar.close()
200 |
201 | print("Saving GraphNVP model trained with maximum liklihood")
202 | model_path = joinpath(args.model_save_dir, 'epoch{}-mle.ckpt'.format(epoch))
203 | torch.save(model.state_dict(), model_path)
204 | print('Saved model checkpoints into {}...'.format(args.model_save_dir))
205 | gen(model, epoch)
206 |
207 | def gen(model, epoch=-1):
208 | model.eval()
209 | all_smiles = []
210 | pure_valids = []
211 | appear_in_train = 0.
212 | start_t = time()
213 | cnt_mol = 0
214 | cnt_gen = 0
215 | out_path = joinpath(args.gen_path, 'mle_mols{}.txt'.format(epoch))
216 | print("Generating %d mols for evaluation" % (args.num_gen))
217 | while cnt_mol < args.num_gen:
218 | smiles, A, X, no_resample, num_atoms = generate_one(model, mute=False, cnt=cnt_gen)
219 | cnt_gen += 1
220 | if cnt_gen > args.max_resample:
221 | break
222 | if num_atoms < 0 or num_atoms < args.min_atoms:
223 | print('#atoms of generated molecule less than %d, discarded!' % args.min_atoms)
224 | continue
225 | else:
226 | cnt_mol += 1
227 | if cnt_mol % 100 == 0:
228 | print('cur cnt mol: %d' % cnt_mol)
229 | all_smiles.append(smiles)
230 | pure_valids.append(no_resample)
231 | print('Accepting: {}'.format(smiles))
232 | if all_train_smiles is not None and smiles in all_train_smiles:
233 | appear_in_train += 1.0
234 | mol = Chem.MolFromSmiles(smiles)
235 | qed_score = env.qed(mol)
236 | plogp_score = env.penalized_logp(mol)
237 | if cnt_mol > args.num_gen:
238 | print("Generating {} times rather than 100 times!".format(cnt_mol))
239 | args.num_gen = cnt_mol
240 |
241 | unique_smiles = list(set(all_smiles))
242 | unique_rate = len(unique_smiles) / args.num_gen
243 | pure_valid_rate = sum(pure_valids) / args.num_gen
244 | novelty = 1. - (appear_in_train / args.num_gen)
245 |
246 | print('Time for generating (%d/%d) molecules(#atoms>=%d) with %d resamplings: %.5f' % (
247 | cnt_gen-args.max_resample, args.num_gen, args.min_atoms, args.max_resample, time() - start_t))
248 | print('| unique rate: %.5f | valid rate: %.5f | novelty: %.5f |' % (unique_rate, pure_valid_rate, novelty))
249 | mol_img_dir = joinpath(args.img_dir, 'mol_img{}'.format(epoch))
250 | os.makedirs(mol_img_dir, exist_ok=True)
251 | if not os.path.exists(args.gen_path):
252 | os.makedirs(args.gen_path)
253 | if out_path is not None and args.save:
254 | with open(out_path, 'w+') as out_file:
255 | cnt = 0
256 | for i, mol in enumerate(all_smiles):
257 | # Invalid disconnection
258 | if '.' in all_smiles[i]:
259 | continue
260 | out_file.write(all_smiles[i] + '\n')
261 | save_mol_png(Chem.MolFromSmiles(mol), joinpath(mol_img_dir, '{}.png'.format(i)))
262 | cnt += 1
263 | print('writing %d smiles into %s done!' % (cnt, out_path))
264 | all_unique_rate.append(unique_rate)
265 | all_valid_rate.append(pure_valid_rate)
266 | all_novelty_rate.append(novelty)
267 | if args.save:
268 | print('saving metric of validity, novelty and uniqueness into %s' %(args.gen_path))
269 | np.save(joinpath(args.gen_path, 'valid{}'.format(epoch)), np.array(all_valid_rate))
270 | np.save(joinpath(args.gen_path, 'novelty{}'.format(epoch)), np.array(all_novelty_rate))
271 | np.save(joinpath(args.gen_path, 'unique{}'.format(epoch)), np.array(all_unique_rate))
272 |
273 | if args.mode == 'train':
274 | train(model)
275 | elif args.mode == 'gen':
276 | gen(model)
277 | else:
278 | print("Specify mode as 'train' or 'gen'")
279 |
280 | if __name__ == '__main__':
281 | random.seed(args.seed)
282 | np.random.seed(args.seed)
283 | torch.manual_seed(args.seed)
284 | main()
--------------------------------------------------------------------------------
/utils/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hlzhang109/PyTorch-GraphNVP/eb6cabd1e5e39f84ffe92662ef5d667aa4e30db3/utils/__init__.py
--------------------------------------------------------------------------------
/utils/argparser.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | from distutils.util import strtobool
3 |
4 | def get_parser():
5 | parser = argparse.ArgumentParser(description='argparser')
6 | # data I/O
7 | parser.add_argument('--data_dir', type=str, default='./data', help='Location for the dataset')
8 | parser.add_argument('--data_path', type=str, default='./data/qm9', help='path for loading data and dataconfig')
9 | parser.add_argument('--data_name', type=str, default='qm9', choices=['qm9', 'zinc250k'], help='dataset name')
10 | parser.add_argument('--data_file', type=str, default='qm9_relgcn_kekulized_ggnp.npz', help='Name of the dataset')
11 | parser.add_argument('--save_dir', type=str, default='./results',
12 | help='Location for parameter checkpoints and samples')
13 | parser.add_argument('--epochs', type=int, default=20, help='Num of epochs to run in total')
14 | parser.add_argument('--device', type=str, default='cuda', help='cpu or cuda')
15 | # reproducibility
16 | parser.add_argument('--seed', type=int, default=1, help='Random seed to use')
17 | parser.add_argument('--num_atoms', type=int, default=9, help='Maximum number of atoms in a molecule')
18 | parser.add_argument('--num_rels', type=int, default=4, help='Number of bond types')
19 | parser.add_argument('--num_atom_types', type=int, default=4, help='Types of atoms that can be used in a molecule')
20 | parser.add_argument('--num_node_masks', type=int, default=9,
21 | help='Number of node masks to be used in coupling layers')
22 | parser.add_argument('--num_channel_masks', type=int, default=4,
23 | help='Number of channel masks to be used in coupling layers')
24 | parser.add_argument('--num_node_coupling', type=int, default=12, help='Number of coupling layers with node masking')
25 | parser.add_argument('--num_channel_coupling', type=int, default=6,
26 | help='Number of coupling layers with channel masking')
27 | parser.add_argument('--node_mask_size', type=int, default=5, help='Number of cells to be masked in the Node '
28 | 'coupling layer')
29 | parser.add_argument('--channel_mask_size', type=int, default=-1, help='Number of cells to be masked in the Channel '
30 | 'coupling layer')
31 | parser.add_argument('--apply_batch_norm', type=bool, default=False, help='Whether batch '
32 | 'normalization should be performed')
33 | parser.add_argument('--additive_transformations', type=bool, default=True,
34 | help='if True, apply only addictive coupling layers; else, apply affine coupling layers')
35 | # Model configuration.
36 | parser.add_argument('--temp', type=float, default=0.7, help='the tempearture of mcmc steps')
37 | parser.add_argument('--use_switch', type=bool, default=False, help='use switch activation for R-GCN')
38 | parser.add_argument('--num_gcn_layer', type=int, default=3)
39 | parser.add_argument('--show_loss_step', type=int, default=10, help='show loss every n step/epoch')
40 |
41 | # Training configuration
42 | parser.add_argument('--batch_size', type=int, default=16, help='mini-batch size')
43 | parser.add_argument('--mle_lr', type=float, default=0.001, help='learning rate for MLE')
44 | parser.add_argument('-lr_decay_factor', default=0.5, type=float, help='learning rate decay factor')
45 | parser.add_argument('-lr_decay_patience', default=200, type=float, help='learning rate decay patience')
46 | parser.add_argument('-lr_decay_min', default=0.00001, type=float, help='learning rate decay min')
47 | parser.add_argument('--dropout', type=float, default=0., help='dropout rate')
48 | parser.add_argument('--beta1', type=float, default=0.5, help='beta1 for Adam optimizer')
49 | parser.add_argument('--beta2', type=float, default=0.9, help='beta2 for Adam optimizer')
50 | parser.add_argument('--resume_epoch', type=int, default=0, help='resume training after this epoch')
51 | parser.add_argument('--resume', type=bool, default=False, help='resume training')
52 |
53 | # Generation args
54 | parser.add_argument('--min_atoms', type=int, default=2, help='Minimum number of atoms in a generated molecule')
55 | parser.add_argument('--num_gen', type=int, default=100, help='num of molecules to generate on each call to train.generate')
56 | parser.add_argument('--min_gen_epoch', type=int, default=5, help='num of molecules to generate on each call to train.generate')
57 | parser.add_argument('--max_resample', type=int, default=200, help='the times of resampling each epoch')
58 | parser.add_argument('--atomic_num_list', type=int, default=[6, 7, 8, 9, 0],
59 | help='atomic number list for datasets')
60 | #parser.add_argument('--post_method', type=str, default='softmax', choices=['softmax', 'soft_gumbel', 'hard_gumbel'],
61 | # help='TODO: postprocessing to convert continuous A and X to discrete ones')
62 | # Miscellaneous.
63 | parser.add_argument('--num_workers', type=int, default=1)
64 | parser.add_argument('--mode', type=str, default='train', choices=['train', 'gen'])
65 | parser.add_argument('--save', action='store_true', default=True, help='Save model.')
66 | # Directories.
67 | parser.add_argument('--log_dir', type=str, default='./logs')
68 | parser.add_argument('--model_save_dir', type=str, default='./saved_models')
69 | parser.add_argument('--sample_dir', type=str, default='./samples')
70 | parser.add_argument('--result_dir', type=str, default='./results')
71 | parser.add_argument('--img_dir', type=str, default='./results/qm9_img')
72 | parser.add_argument('--gen_path', type=str, default='./results/mols', help='output path for generated mol')
73 | parser.add_argument('--model_name', type=str, default='mle', help='model name, crucial for test and checkpoint initialization [epoch3_1gpu]')
74 | return parser
75 |
76 | parser = get_parser()
77 | args = parser.parse_args()
78 |
79 | #Step size.
80 | #parser.add_argument('--log_step', type=int, default=10)
81 | #parser.add_argument('--sample_step', type=int, default=1000)
82 | #parser.add_argument('--model_save_step', type=int, default=1000)
83 | #parser.add_argument('--lr_update_step', type=int, default=1000)
--------------------------------------------------------------------------------
/utils/data_utils.py:
--------------------------------------------------------------------------------
1 | import chainer
2 | import chainer.functions as chainerF
3 | import numpy as np
4 | from chainer.backends import cuda
5 | from rdkit import Chem
6 | from rdkit.Chem import Draw
7 | import torch
8 |
9 | atom_decoder_m = {0: 6, 1: 7, 2: 8, 3: 9, 4: 15, 5: 16, 6: 17, 7: 35, 8: 53}
10 | bond_decoder_m = {1: Chem.rdchem.BondType.SINGLE, 2: Chem.rdchem.BondType.DOUBLE, 3: Chem.rdchem.BondType.TRIPLE}
11 |
12 |
13 | def flatten_graph_data(adj, x):
14 | return torch.cat((adj.view(adj.shape[0], -1),
15 | x.view(x.shape[0], -1)), -1)
16 |
17 | def split_channel(x):
18 | n = x.shape[1] // 2
19 | return x[:, :n], x[:, n:]
20 |
21 | def get_graph_data(x, num_nodes, num_relations, num_features):
22 | """
23 | Converts a vector of shape [b, num_nodes, m] to Adjacency matrix
24 | of shape [b, num_relations, num_nodes, num_nodes]
25 | and a feature matrix of shape [b, num_nodes, num_features].
26 | :param x:
27 | :param num_nodes:
28 | :param num_relations:
29 | :param num_features:
30 | :return:
31 | """
32 | adj = x[:, :num_nodes*num_nodes*num_relations].view(
33 | -1, num_relations, num_nodes, num_nodes)
34 | feat_mat = x[:, num_nodes*num_nodes*num_relations:].view(
35 | -1, num_nodes, num_features)
36 | return adj, feat_mat
37 |
38 |
39 | def Tensor2Mol(A, x):
40 | mol = Chem.RWMol()
41 | # x[x < 0] = 0.
42 | # A[A < 0] = -1
43 | # atoms_exist = np.sum(x, 1) != 0
44 | atoms = torch.argmax(x, 1)
45 | atoms_exist = atoms != 4
46 | atoms = atoms[atoms_exist]
47 | atoms += 6
48 | adj = torch.argmax(A, 0)
49 | #adj = np.array(adj)
50 | adj = adj[atoms_exist, :][:, atoms_exist]
51 | adj[adj == 3] = -1
52 | adj += 1
53 | # print('num atoms: {}'.format(sum(atoms>0)))
54 |
55 | for atom in atoms:
56 | mol.AddAtom(Chem.Atom(int(atom)))
57 |
58 | for start, end in torch.nonzero(adj):
59 | if start > end:
60 | mol.AddBond(int(start), int(end), bond_decoder_m[adj[int(start), int(end)]])
61 |
62 | return mol
63 |
64 |
65 | def construct_mol(X, A, atomic_num_list):
66 | mol = Chem.RWMol()
67 | # x (ch, num_node)
68 | atoms = torch.argmax(X, axis=1)
69 | # last a
70 | atoms_exist = atoms != len(atomic_num_list) - 1
71 | atoms = atoms[atoms_exist]
72 | # print('num atoms: {}'.format(sum(atoms>0)))
73 |
74 | for atom in atoms:
75 | mol.AddAtom(Chem.Atom(int(atomic_num_list[atom])))
76 |
77 | # A (edge_type, num_node, num_node)
78 | adj = torch.argmax(A, axis=0)
79 | adj = adj[atoms_exist, :][:, atoms_exist]
80 | adj[adj == 3] = -1
81 | adj += 1
82 | for start, end in torch.nonzero(adj):
83 | if start > end:
84 | mol.AddBond(start.int().item(), end.int().item(), \
85 | bond_decoder_m[int(adj[start.int().item(), end.int().item()])])
86 | return mol
87 |
88 |
89 | def valid_mol(x):
90 | s = Chem.MolFromSmiles(Chem.MolToSmiles(x)) if x is not None else None
91 | if s is not None and '.' not in Chem.MolToSmiles(s):
92 | return s
93 | return None
94 |
95 |
96 | def check_tensor(x):
97 | return valid_mol(Tensor2Mol(*x))
98 |
99 |
100 | def adj_to_smiles(adj, x, atomic_num_list, gpu=-1):
101 | valid = [Chem.MolToSmiles(construct_mol(x_elem, adj_elem, atomic_num_list))
102 | for x_elem, adj_elem in zip(x, adj)]
103 | return valid
104 |
105 |
106 | def check_validity(adj, x, atomic_num_list, gpu=-1, return_unique=True):
107 | valid = [valid_mol(construct_mol(x_elem, adj_elem, atomic_num_list))
108 | for x_elem, adj_elem in zip(x, adj)]
109 | valid = [mol for mol in valid if mol is not None]
110 | print("valid molecules: {}/{}".format(len(valid), adj.shape[0]))
111 | for i, mol in enumerate(valid):
112 | print("[{}] {}".format(i, Chem.MolToSmiles(mol)))
113 |
114 | n_mols = x.shape[0]
115 | valid_ratio = len(valid)/n_mols
116 | valid_smiles = [Chem.MolToSmiles(mol) for mol in valid]
117 | unique_smiles = list(set(valid_smiles))
118 | unique_ratio = 0.
119 | if len(valid) > 0:
120 | unique_ratio = len(unique_smiles)/len(valid)
121 | if return_unique:
122 | valid_smiles = unique_smiles
123 | valid_mols = [Chem.MolFromSmiles(s) for s in valid_smiles]
124 | print("valid: {:.3f}%, unique: {:.3f}%".format(valid_ratio * 100, unique_ratio * 100))
125 |
126 | results = dict()
127 | results['valid_mols'] = valid_mols
128 | results['valid_smiles'] = valid_smiles
129 | results['valid_ratio'] = valid_ratio*100
130 | results['unique_ratio'] = unique_ratio*100
131 |
132 | return results
133 |
134 |
135 | def check_novelty(gen_smiles, train_smiles):
136 | if len(gen_smiles) == 0:
137 | novel_ratio = 0.
138 | else:
139 | duplicates = [1 for mol in gen_smiles if mol in train_smiles]
140 | novel = len(gen_smiles) - sum(duplicates)
141 | novel_ratio = novel*100./len(gen_smiles)
142 | print("novelty: {}%".format(novel_ratio))
143 | return novel_ratio
144 |
145 | def save_mol_png(mol, filepath, size=(600, 600)):
146 | Draw.MolToFile(mol, filepath, size=size)
--------------------------------------------------------------------------------
/utils/environment.py:
--------------------------------------------------------------------------------
1 | import itertools
2 | import numpy as np
3 | from rdkit import Chem
4 | from rdkit.Chem import AllChem
5 | from rdkit.Chem.Descriptors import qed, MolLogP
6 | from rdkit.Chem import rdMolDescriptors
7 | from rdkit.Chem.FilterCatalog import FilterCatalogParams, FilterCatalog
8 | import copy
9 | import networkx as nx
10 | import math
11 | import random
12 | import time
13 | # import matplotlib.pyplot as plt
14 | import csv
15 |
16 | from contextlib import contextmanager
17 | import sys, os
18 |
19 | from utils.sascorer import calculateScore
20 |
21 | # most of the codes here are taken from GCPN's open-source implementation
22 | '''
23 | Environment Usage
24 | plogp: penalized_logp(mol)
25 | logp: MolLogP(mol)
26 | qed: qed(mol)
27 | sa: calculateScore(mol)
28 | mw: rdMolDescriptors.CalcExactMolWt(mol)
29 | '''
30 |
31 |
32 | def convert_radical_electrons_to_hydrogens(mol):
33 | """
34 | Converts radical electrons in a molecule into bonds to hydrogens. Only
35 | use this if molecule is valid. Results a new mol object
36 | :param mol: rdkit mol object
37 | :return: rdkit mol object
38 | """
39 | m = copy.deepcopy(mol)
40 | if Chem.Descriptors.NumRadicalElectrons(m) == 0: # not a radical
41 | return m
42 | else: # a radical
43 | print('converting radical electrons to H')
44 | for a in m.GetAtoms():
45 | num_radical_e = a.GetNumRadicalElectrons()
46 | if num_radical_e > 0:
47 | a.SetNumRadicalElectrons(0)
48 | a.SetNumExplicitHs(num_radical_e)
49 | return m
50 |
51 |
52 | def check_chemical_validity(mol):
53 | """
54 | Checks the chemical validity of the mol object. Existing mol object is
55 | not modified. Radicals pass this test.
56 | :return: True if chemically valid, False otherwise
57 | """
58 | s = Chem.MolToSmiles(mol, isomericSmiles=True)
59 | m = Chem.MolFromSmiles(s) # implicitly performs sanitization
60 | if m:
61 | return True
62 | else:
63 | return False
64 |
65 |
66 | def check_valency(mol):
67 | """
68 | Checks that no atoms in the mol have exceeded their possible
69 | valency
70 | :return: True if no valency issues, False otherwise
71 | """
72 | try:
73 | Chem.SanitizeMol(mol,
74 | sanitizeOps=Chem.SanitizeFlags.SANITIZE_PROPERTIES)
75 | return True
76 | except ValueError:
77 | return False
78 |
79 |
80 | def get_final_smiles(mol):
81 | """
82 | Returns a SMILES of the final molecule. Converts any radical
83 | electrons into hydrogens. Works only if molecule is valid
84 | :return: SMILES
85 | """
86 | m = convert_radical_electrons_to_hydrogens(mol)
87 | return Chem.MolToSmiles(m, isomericSmiles=True)
88 |
89 |
90 | def get_final_mol(mol):
91 | """
92 | Returns a rdkit mol object of the final molecule. Converts any radical
93 | electrons into hydrogens. Works only if molecule is valid
94 | :return: SMILES
95 | """
96 | m = convert_radical_electrons_to_hydrogens(mol)
97 | return m
98 |
99 |
100 | def add_hydrogen(mol):
101 | s = Chem.MolToSmiles(mol, isomericSmiles=True)
102 | return Chem.MolFromSmiles(s)
103 |
104 |
105 | def calculate_min_plogp(mol):
106 | p1 = penalized_logp(mol)
107 | s1 = Chem.MolToSmiles(mol, isomericSmiles=True)
108 | s2 = Chem.MolToSmiles(mol, isomericSmiles=False)
109 | mol1 = Chem.MolFromSmiles(s1)
110 | mol2 = Chem.MolFromSmiles(s2)
111 | p2 = penalized_logp(mol1)
112 | p3 = penalized_logp(mol2)
113 | final_p = min(p1, p2)
114 | final_p = min(final_p, p3)
115 | return final_p
116 |
117 |
118 | def penalized_logp(mol):
119 | """
120 | Reward that consists of log p penalized by SA and # long cycles,
121 | as described in (Kusner et al. 2017). Scores are normalized based on the
122 | statistics of 250k_rndm_zinc_drugs_clean.smi dataset
123 | :param mol: rdkit mol object
124 | :return: float
125 | """
126 | # normalization constants, statistics from 250k_rndm_zinc_drugs_clean.smi
127 | logP_mean = 2.4570953396190123
128 | logP_std = 1.434324401111988
129 | SA_mean = -3.0525811293166134
130 | SA_std = 0.8335207024513095
131 | cycle_mean = -0.0485696876403053
132 | cycle_std = 0.2860212110245455
133 |
134 | log_p = MolLogP(mol)
135 | SA = -calculateScore(mol)
136 |
137 | # cycle score
138 | cycle_list = nx.cycle_basis(nx.Graph(
139 | Chem.rdmolops.GetAdjacencyMatrix(mol)))
140 | if len(cycle_list) == 0:
141 | cycle_length = 0
142 | else:
143 | cycle_length = max([len(j) for j in cycle_list])
144 | if cycle_length <= 6:
145 | cycle_length = 0
146 | else:
147 | cycle_length = cycle_length - 6
148 | cycle_score = -cycle_length
149 |
150 | normalized_log_p = (log_p - logP_mean) / logP_std
151 | normalized_SA = (SA - SA_mean) / SA_std
152 | normalized_cycle = (cycle_score - cycle_mean) / cycle_std
153 |
154 | return normalized_log_p + normalized_SA + normalized_cycle
155 |
156 |
157 | def steric_strain_filter(mol, cutoff=0.82, max_attempts_embed=20, max_num_iters=200):
158 | """
159 | Flags molecules based on a steric energy cutoff after max_num_iters
160 | iterations of MMFF94 forcefield minimization. Cutoff is based on average
161 | angle bend strain energy of molecule
162 | :param mol: rdkit mol object
163 | :param cutoff: kcal/mol per angle . If minimized energy is above this
164 | threshold, then molecule fails the steric strain filter
165 | :param max_attempts_embed: number of attempts to generate initial 3d
166 | coordinates
167 | :param max_num_iters: number of iterations of forcefield minimization
168 | :return: True if molecule could be successfully minimized, and resulting
169 | energy is below cutoff, otherwise False
170 | """
171 | # check for the trivial cases of a single atom or only 2 atoms, in which
172 | # case there is no angle bend strain energy (as there are no angles!)
173 | if mol.GetNumAtoms() <= 2:
174 | return True
175 |
176 | # make copy of input mol and add hydrogens
177 | m = copy.deepcopy(mol)
178 | m_h = Chem.AddHs(m)
179 |
180 | # generate an initial 3d conformer
181 | try:
182 | flag = AllChem.EmbedMolecule(m_h, maxAttempts=max_attempts_embed)
183 | if flag == -1:
184 | # print("Unable to generate 3d conformer")
185 | return False
186 | except: # to catch error caused by molecules such as C=[SH]1=C2OC21ON(N)OC(=O)NO
187 | # print("Unable to generate 3d conformer")
188 | return False
189 |
190 | # set up the forcefield
191 | AllChem.MMFFSanitizeMolecule(m_h)
192 | if AllChem.MMFFHasAllMoleculeParams(m_h):
193 | mmff_props = AllChem.MMFFGetMoleculeProperties(m_h)
194 | try: # to deal with molecules such as CNN1NS23(=C4C5=C2C(=C53)N4Cl)S1
195 | ff = AllChem.MMFFGetMoleculeForceField(m_h, mmff_props)
196 | except:
197 | # print("Unable to get forcefield or sanitization error")
198 | return False
199 | else:
200 | # print("Unrecognized atom type")
201 | return False
202 |
203 | # minimize steric energy
204 | try:
205 | ff.Minimize(maxIts=max_num_iters)
206 | except:
207 | # print("Minimization error")
208 | return False
209 |
210 | # ### debug ###
211 | # min_e = ff.CalcEnergy()
212 | # print("Minimized energy: {}".format(min_e))
213 | # ### debug ###
214 |
215 | # get the angle bend term contribution to the total molecule strain energy
216 | mmff_props.SetMMFFBondTerm(False)
217 | mmff_props.SetMMFFAngleTerm(True)
218 | mmff_props.SetMMFFStretchBendTerm(False)
219 | mmff_props.SetMMFFOopTerm(False)
220 | mmff_props.SetMMFFTorsionTerm(False)
221 | mmff_props.SetMMFFVdWTerm(False)
222 | mmff_props.SetMMFFEleTerm(False)
223 |
224 | ff = AllChem.MMFFGetMoleculeForceField(m_h, mmff_props)
225 |
226 | min_angle_e = ff.CalcEnergy()
227 | # print("Minimized angle bend energy: {}".format(min_angle_e))
228 |
229 | # find number of angles in molecule
230 | # from molecule... This is too hacky
231 | num_atoms = m_h.GetNumAtoms()
232 | atom_indices = range(num_atoms)
233 | angle_atom_triplets = itertools.permutations(atom_indices, 3) # get all
234 | # possible 3 atom indices groups. Currently, each angle is represented by
235 | # 2 duplicate groups. Should remove duplicates here to be more efficient
236 | double_num_angles = 0
237 | for triplet in list(angle_atom_triplets):
238 | if mmff_props.GetMMFFAngleBendParams(m_h, *triplet):
239 | double_num_angles += 1
240 | num_angles = double_num_angles / 2 # account for duplicate angles
241 |
242 | # print("Number of angles: {}".format(num_angles))
243 |
244 | avr_angle_e = min_angle_e / num_angles
245 |
246 | # print("Average minimized angle bend energy: {}".format(avr_angle_e))
247 | if avr_angle_e < cutoff:
248 | return True
249 | else:
250 | return False
251 |
252 | ### YES/NO filters ###
253 | def zinc_molecule_filter(mol):
254 | """
255 | Flags molecules based on problematic functional groups as
256 | provided set of ZINC rules from
257 | http://blaster.docking.org/filtering/rules_default.txt.
258 | :param mol: rdkit mol object
259 | :return: Returns True if molecule is okay (ie does not match any of
260 | therules), False if otherwise
261 | """
262 | params = FilterCatalogParams()
263 | params.AddCatalog(FilterCatalogParams.FilterCatalogs.ZINC)
264 | catalog = FilterCatalog(params)
265 | return not catalog.HasMatch(mol)
--------------------------------------------------------------------------------
/utils/fpscores.pkl.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hlzhang109/PyTorch-GraphNVP/eb6cabd1e5e39f84ffe92662ef5d667aa4e30db3/utils/fpscores.pkl.gz
--------------------------------------------------------------------------------
/utils/molecular_metrics.py:
--------------------------------------------------------------------------------
1 | """
2 | Original code from MolGAN by @nicola-decao under MIT license
3 | https://github.com/nicola-decao/MolGAN/blob/master/utils/molecular_metrics.py
4 | """
5 | import pickle
6 | import gzip
7 | from rdkit import DataStructs
8 | from rdkit import Chem
9 | from rdkit.Chem import QED
10 | from rdkit.Chem import Crippen
11 |
12 | import math
13 | import numpy as np
14 |
15 | # NP_model = pickle.load(gzip.open('data/NP_score.pkl.gz'))
16 | # SA_model = {i[j]: float(i[0]) for i in pickle.load(gzip.open('data/SA_score.pkl.gz')) for j in range(1, len(i))}
17 | NP_model = None
18 | SA_model = None
19 |
20 |
21 | class MolecularMetrics(object):
22 |
23 | @staticmethod
24 | def _avoid_sanitization_error(op):
25 | try:
26 | return op()
27 | except ValueError:
28 | return None
29 |
30 | @staticmethod
31 | def remap(x, x_min, x_max):
32 | return (x - x_min) / (x_max - x_min)
33 |
34 | @staticmethod
35 | def valid_lambda(x):
36 | return x is not None and Chem.MolToSmiles(x) != ''
37 |
38 | @staticmethod
39 | def valid_lambda_special(x):
40 | s = Chem.MolToSmiles(x) if x is not None else ''
41 | return x is not None and '*' not in s and '.' not in s and s != ''
42 |
43 | @staticmethod
44 | def valid_scores(mols):
45 | return np.array(list(map(MolecularMetrics.valid_lambda_special, mols)), dtype=np.float32)
46 |
47 | @staticmethod
48 | def valid_filter(mols):
49 | return list(filter(MolecularMetrics.valid_lambda, mols))
50 |
51 | @staticmethod
52 | def valid_total_score(mols):
53 | return np.array(list(map(MolecularMetrics.valid_lambda, mols)), dtype=np.float32).mean()
54 |
55 | @staticmethod
56 | def novel_scores(mols, data):
57 | return np.array(
58 | list(map(lambda x: MolecularMetrics.valid_lambda(x) and Chem.MolToSmiles(x) not in data.smiles, mols)))
59 |
60 | @staticmethod
61 | def novel_filter(mols, data):
62 | return list(filter(lambda x: MolecularMetrics.valid_lambda(x) and Chem.MolToSmiles(x) not in data.smiles, mols))
63 |
64 | @staticmethod
65 | def novel_total_score(mols, data):
66 | return MolecularMetrics.novel_scores(MolecularMetrics.valid_filter(mols), data).mean()
67 |
68 | @staticmethod
69 | def unique_scores(mols):
70 | smiles = list(map(lambda x: Chem.MolToSmiles(x) if MolecularMetrics.valid_lambda(x) else '', mols))
71 | return np.clip(
72 | 0.75 + np.array(list(map(lambda x: 1 / smiles.count(x) if x != '' else 0, smiles)), dtype=np.float32), 0, 1)
73 |
74 | @staticmethod
75 | def unique_total_score(mols):
76 | v = MolecularMetrics.valid_filter(mols)
77 | s = set(map(lambda x: Chem.MolToSmiles(x), v))
78 | return 0 if len(v) == 0 else len(s) / len(v)
79 |
80 | # @staticmethod
81 | # def novel_and_unique_total_score(mols, data):
82 | # return ((MolecularMetrics.unique_scores(mols) == 1).astype(float) * MolecularMetrics.novel_scores(mols,
83 | # data)).sum()
84 | #
85 | # @staticmethod
86 | # def reconstruction_scores(data, model, session, sample=False):
87 | #
88 | # m0, _, _, a, x, _, f, _, _ = data.next_validation_batch()
89 | # feed_dict = {model.edges_labels: a, model.nodes_labels: x, model.node_features: f, model.training: False}
90 | #
91 | # try:
92 | # feed_dict.update({model.variational: False})
93 | # except AttributeError:
94 | # pass
95 | #
96 | # n, e = session.run([model.nodes_gumbel_argmax, model.edges_gumbel_argmax] if sample else [
97 | # model.nodes_argmax, model.edges_argmax], feed_dict=feed_dict)
98 | #
99 | # n, e = np.argmax(n, axis=-1), np.argmax(e, axis=-1)
100 | #
101 | # m1 = [data.matrices2mol(n_, e_, strict=True) for n_, e_ in zip(n, e)]
102 | #
103 | # return np.mean([float(Chem.MolToSmiles(m0_) == Chem.MolToSmiles(m1_)) if m1_ is not None else 0
104 | # for m0_, m1_ in zip(m0, m1)])
105 |
106 | @staticmethod
107 | def natural_product_scores(mols, norm=False):
108 |
109 | # calculating the score
110 | scores = [sum(NP_model.get(bit, 0)
111 | for bit in Chem.rdMolDescriptors.GetMorganFingerprint(mol,
112 | 2).GetNonzeroElements()) / float(
113 | mol.GetNumAtoms()) if mol is not None else None
114 | for mol in mols]
115 |
116 | # preventing score explosion for exotic molecules
117 | scores = list(map(lambda score: score if score is None else (
118 | 4 + math.log10(score - 4 + 1) if score > 4 else (
119 | -4 - math.log10(-4 - score + 1) if score < -4 else score)), scores))
120 |
121 | scores = np.array(list(map(lambda x: -4 if x is None else x, scores)))
122 | scores = np.clip(MolecularMetrics.remap(scores, -3, 1), 0.0, 1.0) if norm else scores
123 |
124 | return scores
125 |
126 | @staticmethod
127 | def quantitative_estimation_druglikeness_scores(mols, norm=False):
128 | return np.array(list(map(lambda x: 0 if x is None else x, [
129 | MolecularMetrics._avoid_sanitization_error(lambda: QED.qed(mol)) if mol is not None else None for mol in
130 | mols])))
131 |
132 | @staticmethod
133 | def water_octanol_partition_coefficient_scores(mols, norm=False):
134 | scores = [MolecularMetrics._avoid_sanitization_error(lambda: Crippen.MolLogP(Chem.AddHs(mol, 1))) if mol is not None else None
135 | for mol in mols]
136 | scores = np.array(list(map(lambda x: -3 if x is None else x, scores)))
137 | scores = np.clip(MolecularMetrics.remap(scores, -2.12178879609, 6.0429063424), 0.0, 1.0) if norm else scores
138 |
139 | return scores
140 |
141 | @staticmethod
142 | def _compute_SAS(mol):
143 | fp = Chem.rdMolDescriptors.GetMorganFingerprint(mol, 2)
144 | fps = fp.GetNonzeroElements()
145 | score1 = 0.
146 | nf = 0
147 | # for bitId, v in fps.items():
148 | for bitId, v in fps.items():
149 | nf += v
150 | sfp = bitId
151 | score1 += SA_model.get(sfp, -4) * v
152 | score1 /= nf
153 |
154 | # features score
155 | nAtoms = mol.GetNumAtoms()
156 | nChiralCenters = len(Chem.FindMolChiralCenters(
157 | mol, includeUnassigned=True))
158 | ri = mol.GetRingInfo()
159 | nSpiro = Chem.rdMolDescriptors.CalcNumSpiroAtoms(mol)
160 | nBridgeheads = Chem.rdMolDescriptors.CalcNumBridgeheadAtoms(mol)
161 | nMacrocycles = 0
162 | for x in ri.AtomRings():
163 | if len(x) > 8:
164 | nMacrocycles += 1
165 |
166 | sizePenalty = nAtoms ** 1.005 - nAtoms
167 | stereoPenalty = math.log10(nChiralCenters + 1)
168 | spiroPenalty = math.log10(nSpiro + 1)
169 | bridgePenalty = math.log10(nBridgeheads + 1)
170 | macrocyclePenalty = 0.
171 |
172 | # ---------------------------------------
173 | # This differs from the paper, which defines:
174 | # macrocyclePenalty = math.log10(nMacrocycles+1)
175 | # This form generates better results when 2 or more macrocycles are present
176 | if nMacrocycles > 0:
177 | macrocyclePenalty = math.log10(2)
178 |
179 | score2 = 0. - sizePenalty - stereoPenalty - \
180 | spiroPenalty - bridgePenalty - macrocyclePenalty
181 |
182 | # correction for the fingerprint density
183 | # not in the original publication, added in version 1.1
184 | # to make highly symmetrical molecules easier to synthetise
185 | score3 = 0.
186 | if nAtoms > len(fps):
187 | score3 = math.log(float(nAtoms) / len(fps)) * .5
188 |
189 | sascore = score1 + score2 + score3
190 |
191 | # need to transform "raw" value into scale between 1 and 10
192 | min = -4.0
193 | max = 2.5
194 | sascore = 11. - (sascore - min + 1) / (max - min) * 9.
195 | # smooth the 10-end
196 | if sascore > 8.:
197 | sascore = 8. + math.log(sascore + 1. - 9.)
198 | if sascore > 10.:
199 | sascore = 10.0
200 | elif sascore < 1.:
201 | sascore = 1.0
202 |
203 | return sascore
204 |
205 | @staticmethod
206 | def synthetic_accessibility_score_scores(mols, norm=False):
207 | scores = [MolecularMetrics._compute_SAS(mol) if mol is not None else None for mol in mols]
208 | scores = np.array(list(map(lambda x: 10 if x is None else x, scores)))
209 | scores = np.clip(MolecularMetrics.remap(scores, 5, 1.5), 0.0, 1.0) if norm else scores
210 |
211 | return scores
212 |
213 | @staticmethod
214 | def diversity_scores(mols, data):
215 | rand_mols = np.random.choice(data.data, 100)
216 | fps = [Chem.rdMolDescriptors.GetMorganFingerprintAsBitVect(mol, 4, nBits=2048) for mol in rand_mols]
217 |
218 | scores = np.array(
219 | list(map(lambda x: MolecularMetrics.__compute_diversity(x, fps) if x is not None else 0, mols)))
220 | scores = np.clip(MolecularMetrics.remap(scores, 0.9, 0.945), 0.0, 1.0)
221 |
222 | return scores
223 |
224 | @staticmethod
225 | def __compute_diversity(mol, fps):
226 | ref_fps = Chem.rdMolDescriptors.GetMorganFingerprintAsBitVect(mol, 4, nBits=2048)
227 | dist = DataStructs.BulkTanimotoSimilarity(ref_fps, fps, returnDistance=True)
228 | score = np.mean(dist)
229 | return score
230 |
231 | @staticmethod
232 | def drugcandidate_scores(mols, data):
233 |
234 | scores = (MolecularMetrics.constant_bump(
235 | MolecularMetrics.water_octanol_partition_coefficient_scores(mols, norm=True), 0.210,
236 | 0.945) + MolecularMetrics.synthetic_accessibility_score_scores(mols,
237 | norm=True) + MolecularMetrics.novel_scores(
238 | mols, data) + (1 - MolecularMetrics.novel_scores(mols, data)) * 0.3) / 4
239 |
240 | return scores
241 |
242 | @staticmethod
243 | def constant_bump(x, x_low, x_high, decay=0.025):
244 | return np.select(condlist=[x <= x_low, x >= x_high],
245 | choicelist=[np.exp(- (x - x_low) ** 2 / decay),
246 | np.exp(- (x - x_high) ** 2 / decay)],
247 | default=np.ones_like(x))
248 |
249 |
250 | def quantitative_estimation_druglikeness_scores(mols, norm=False):
251 | return np.array(list(map(lambda x: 0 if x is None else x, [
252 | MolecularMetrics._avoid_sanitization_error(lambda: QED.qed(mol)) if mol is not None else None for mol in
253 | mols])))
--------------------------------------------------------------------------------
/utils/sascorer.py:
--------------------------------------------------------------------------------
1 | #
2 | # calculation of synthetic accessibility score as described in:
3 | #
4 | # Estimation of Synthetic Accessibility Score of Drug-like Molecules based on Molecular Complexity and Fragment Contributions
5 | # Peter Ertl and Ansgar Schuffenhauer
6 | # Journal of Cheminformatics 1:8 (2009)
7 | # http://www.jcheminf.com/content/1/1/8
8 | #
9 | # several small modifications to the original paper are included
10 | # particularly slightly different formula for marocyclic penalty
11 | # and taking into account also molecule symmetry (fingerprint density)
12 | #
13 | # for a set of 10k diverse molecules the agreement between the original method
14 | # as implemented in PipelinePilot and this implementation is r2 = 0.97
15 | #
16 | # peter ertl & greg landrum, september 2013
17 | #
18 | from __future__ import print_function
19 |
20 | from rdkit import Chem
21 | from rdkit.Chem import rdMolDescriptors
22 | # from rdkit.six.moves import cPickle
23 | import pickle as cPickle
24 | from rdkit.six import iteritems
25 |
26 | import math
27 | from collections import defaultdict
28 |
29 | import os.path as op
30 |
31 | _fscores = None
32 |
33 |
34 | def readFragmentScores(name='fpscores'):
35 | import gzip
36 | global _fscores
37 | # generate the full path filename:
38 | if name == "fpscores":
39 | name = op.join(op.dirname(__file__), name)
40 | _fscores = cPickle.load(gzip.open('%s.pkl.gz' % name))
41 | outDict = {}
42 | for i in _fscores:
43 | for j in range(1, len(i)):
44 | outDict[i[j]] = float(i[0])
45 | _fscores = outDict
46 |
47 |
48 | def numBridgeheadsAndSpiro(mol, ri=None):
49 | nSpiro = rdMolDescriptors.CalcNumSpiroAtoms(mol)
50 | nBridgehead = rdMolDescriptors.CalcNumBridgeheadAtoms(mol)
51 | return nBridgehead, nSpiro
52 |
53 |
54 | def calculateScore(m):
55 | if _fscores is None:
56 | readFragmentScores()
57 |
58 | # fragment score
59 | fp = rdMolDescriptors.GetMorganFingerprint(m, 2) #<- 2 is the *radius* of the circular fingerprint
60 | fps = fp.GetNonzeroElements()
61 | score1 = 0.
62 | nf = 0
63 | for bitId, v in iteritems(fps):
64 | nf += v
65 | sfp = bitId
66 | score1 += _fscores.get(sfp, -4) * v
67 | score1 /= nf
68 |
69 | # features score
70 | nAtoms = m.GetNumAtoms()
71 | nChiralCenters = len(Chem.FindMolChiralCenters(m, includeUnassigned=True))
72 | ri = m.GetRingInfo()
73 | nBridgeheads, nSpiro = numBridgeheadsAndSpiro(m, ri)
74 | nMacrocycles = 0
75 | for x in ri.AtomRings():
76 | if len(x) > 8:
77 | nMacrocycles += 1
78 |
79 | sizePenalty = nAtoms**1.005 - nAtoms
80 | stereoPenalty = math.log10(nChiralCenters + 1)
81 | spiroPenalty = math.log10(nSpiro + 1)
82 | bridgePenalty = math.log10(nBridgeheads + 1)
83 | macrocyclePenalty = 0.
84 | # ---------------------------------------
85 | # This differs from the paper, which defines:
86 | # macrocyclePenalty = math.log10(nMacrocycles+1)
87 | # This form generates better results when 2 or more macrocycles are present
88 | if nMacrocycles > 0:
89 | macrocyclePenalty = math.log10(2)
90 |
91 | score2 = 0. - sizePenalty - stereoPenalty - spiroPenalty - bridgePenalty - macrocyclePenalty
92 |
93 | # correction for the fingerprint density
94 | # not in the original publication, added in version 1.1
95 | # to make highly symmetrical molecules easier to synthetise
96 | score3 = 0.
97 | if nAtoms > len(fps):
98 | score3 = math.log(float(nAtoms) / len(fps)) * .5
99 |
100 | sascore = score1 + score2 + score3
101 |
102 | # need to transform "raw" value into scale between 1 and 10
103 | min = -4.0
104 | max = 2.5
105 | sascore = 11. - (sascore - min + 1) / (max - min) * 9.
106 | # smooth the 10-end
107 | if sascore > 8.:
108 | sascore = 8. + math.log(sascore + 1. - 9.)
109 | if sascore > 10.:
110 | sascore = 10.0
111 | elif sascore < 1.:
112 | sascore = 1.0
113 |
114 | return sascore
115 |
116 |
117 | def processMols(mols):
118 | print('smiles\tName\tsa_score')
119 | for i, m in enumerate(mols):
120 | if m is None:
121 | continue
122 |
123 | s = calculateScore(m)
124 |
125 | smiles = Chem.MolToSmiles(m)
126 | print(smiles + "\t" + m.GetProp('_Name') + "\t%3f" % s)
127 |
128 |
129 | if __name__ == '__main__':
130 | import sys, time
131 |
132 | t1 = time.time()
133 | readFragmentScores("fpscores")
134 | t2 = time.time()
135 |
136 | suppl = Chem.SmilesMolSupplier(sys.argv[1])
137 | t3 = time.time()
138 | processMols(suppl)
139 | t4 = time.time()
140 |
141 | print('Reading took %.2f seconds. Calculating took %.2f seconds' % ((t2 - t1), (t4 - t3)),
142 | file=sys.stderr)
143 |
144 | #
145 | # Copyright (c) 2013, Novartis Institutes for BioMedical Research Inc.
146 | # All rights reserved.
147 | #
148 | # Redistribution and use in source and binary forms, with or without
149 | # modification, are permitted provided that the following conditions are
150 | # met:
151 | #
152 | # * Redistributions of source code must retain the above copyright
153 | # notice, this list of conditions and the following disclaimer.
154 | # * Redistributions in binary form must reproduce the above
155 | # copyright notice, this list of conditions and the following
156 | # disclaimer in the documentation and/or other materials provided
157 | # with the distribution.
158 | # * Neither the name of Novartis Institutes for BioMedical Research Inc.
159 | # nor the names of its contributors may be used to endorse or promote
160 | # products derived from this software without specific prior written permission.
161 | #
162 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
163 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
164 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
165 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
166 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
167 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
168 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
169 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
170 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
171 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
172 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
173 | #
--------------------------------------------------------------------------------