From 27bf00b46f42ce6577546e7c048928f5cddf684e Mon Sep 17 00:00:00 2001 From: boby-cloudforge Date: Sun, 3 May 2026 15:59:09 +0200 Subject: [PATCH] =?UTF-8?q?=E3=80=90Hackathon=2010th=20Spring=20No.7?= =?UTF-8?q?=E3=80=91wD-MPNN=20model=20reproduction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 195 ++++------ docs/MetaX.png | Bin 0 -> 129498 bytes docs/suzhoulab.png | Bin 0 -> 9426 bytes docs/zhonghua.jpeg | Bin 0 -> 45349 bytes .../configs/schnet/schnet_md17_ethanol.yaml | 107 +++++ .../configs/schnet/schnet_qm9_U0.yaml | 109 ++++++ ppmat/datasets/alloy_dataset.py | 88 +++++ ppmat/datasets/md17_dataset.py | 250 ++++++++++++ ppmat/models/__init__.py | 2 + ppmat/models/wd_mpnn/__init__.py | 3 + ppmat/models/wd_mpnn/featurization.py | 169 ++++++++ ppmat/models/wd_mpnn/wd_mpnn.py | 366 ++++++++++++++++++ property_prediction/configs/wd_mpnn/README.md | 49 +++ .../configs/wd_mpnn/wd_mpnn_qm9_homo.yaml | 91 +++++ test/wd_mpnn/__init__.py | 0 test/wd_mpnn/conftest.py | 23 ++ test/wd_mpnn/raw_infer_data/__init__.py | 0 .../raw_infer_data/create_input_output_npz.py | 107 +++++ test/wd_mpnn/raw_infer_data/reference_io.npz | Bin 0 -> 510 bytes test/wd_mpnn/test_loss/__init__.py | 0 .../test_loss/test_model_loss_with_raw.py | 268 +++++++++++++ 21 files changed, 1704 insertions(+), 123 deletions(-) create mode 100644 docs/MetaX.png create mode 100644 docs/suzhoulab.png create mode 100644 docs/zhonghua.jpeg create mode 100644 interatomic_potentials/configs/schnet/schnet_md17_ethanol.yaml create mode 100644 interatomic_potentials/configs/schnet/schnet_qm9_U0.yaml create mode 100644 ppmat/datasets/alloy_dataset.py create mode 100644 ppmat/datasets/md17_dataset.py create mode 100644 ppmat/models/wd_mpnn/__init__.py create mode 100644 ppmat/models/wd_mpnn/featurization.py create mode 100644 ppmat/models/wd_mpnn/wd_mpnn.py create mode 100644 property_prediction/configs/wd_mpnn/README.md create mode 100644 property_prediction/configs/wd_mpnn/wd_mpnn_qm9_homo.yaml create mode 100644 test/wd_mpnn/__init__.py create mode 100644 test/wd_mpnn/conftest.py create mode 100644 test/wd_mpnn/raw_infer_data/__init__.py create mode 100644 test/wd_mpnn/raw_infer_data/create_input_output_npz.py create mode 100644 test/wd_mpnn/raw_infer_data/reference_io.npz create mode 100644 test/wd_mpnn/test_loss/__init__.py create mode 100644 test/wd_mpnn/test_loss/test_model_loss_with_raw.py diff --git a/README.md b/README.md index ddcc5c78..56a4c38e 100755 --- a/README.md +++ b/README.md @@ -6,176 +6,125 @@ ## 🚀 Introduction -**PaddleMaterials** is an end-to-end AI4Materials toolkit built on the **PaddlePaddle** deep learning framework. Designed as a data-mechanism dual-driven platform for developing and deploying foundation models in materials science, **PPMat** enables researchers to efficiently build AI models and accelerate material discovery using pretrained models. +**PaddleMaterials** is a data-mechanism dual-driven, development and deployment of AI4Materials foundation models, end to end toolkit based on PaddlePaddle deep learning framework for materials science and engineering. **PPMat** (represents PaddleMaterials in the following text) is designed to help researchers more efficiently build AI4Materials foundation models and explore, discover, and develop new materials based on deployed pretrained models. **PPMat** has supported inorganic materials and part of organic molecules, and will support more types of materials including polymers, organic molecules, catalysts, and so on. It has supported some representative models including the equivalent graph networks-based model, diffusion model, multi-modal model, and will support more kinds of deep learing models and agents works related to AI4Material fields in the feature.

-### Core Capabilities +**Inorganic materials**, characterized by their symmetrical and periodic structures, exhibit a wide range of properties and are widely applied in various fields, from electronic devices to energy applications. Traditional experimental and computational methods for discovering crystalline materials are often time-consuming and expensive. Data-driven approaches to material discovery have the power to model the highly complex atomic systems within crystalline materials, paving the way for rapid and accurate material discovery. -| Task | Description | Typical Applications | -|------|-------------|---------------------| -| **Property Prediction (PP)** | Predict material properties from structure | Formation energy, band gap, elastic moduli | -| **Structure Generation (SG)** | Generate novel crystal structures | High-throughput screening, inverse design | -| **Interatomic Potential (IP)** | Replace DFT with ML potentials | Molecular dynamics, large-scale simulations | -| **Electronic Structure (ES)** | Predict electronic properties | Band structure, density of states | -| **Spectrum Elucidation (SE)** | Reconstruct structures from spectra | NMR structure elucidation | +**Organic materials**, distinguished by covalently linked, directionally bonded networks, mainly defined as a carbon–hydrogen or carbon–carbon bond chemical compound. These traits support core applications including flexible displays, organic photovoltaics, high-energy-density battery electrodes, advanced separation membranes, catalyts. The vast compositional and conformational space of organic molecules makes trial-and-error synthesis and ab-initio simulations slow and costly. Data-driven methods that fuse high-throughput datasets, graph-based representations, and deep generative models rapidly learn structure–property links, enabling fast virtual screening and rational design for more agile, sustainable advances in organic materials. -### Supported Materials +**Polymer materials**, characterized by their large molecular weight and complex molecular structures and built from long-chain macromolecules with tunable architectures (homopolymer, block, graft) and morphologies (amorphous, semicrystalline, cross-linked), offer lightweight, processable, and programmable mechanical, thermal, optical, and transport properties for coatings, membranes, composites, and flexible electronics. The combinatorial design space—monomer choice, sequence, tacticity, molecular-weight distribution, additives, and processing history—plus multi-scale physics makes Edisonian discovery and brute-force simulation slow and costly. Data-driven polymer informatics that fuses high-throughput measurements with graph/sequence representations and physics-guided neural surrogates learns structure-processing-property links, while generative and active-learning workflows target Tg, modulus, permeability, dielectric constant, and recyclability for rapid, sustainable polymer discovery. -- **Inorganic Crystals** - Well-supported with multiple datasets (MP2018, MP2024, JARVIS) and pretrained models -- **Organic Molecules** - Support for small molecule datasets (QM9) and property prediction -- *Polymers, catalysts, and amorphous materials are under development* +**Catalysts materials**, as key components in chemical reactions, play a crucial role in the development of new materials and technologies and spanning heterogeneous surfaces (metals, alloys, oxides, zeolites), homogeneous/organometallic complexes, and electrocatalysts, control reaction rates and selectivity across chemicals, energy, and environmental remediation. Discovery is hampered by vast compositional/structural spaces, site heterogeneity, competing pathways, and operando effects (adsorption, kinetics, deactivation) that challenge trial-and-error and exhaustive DFT. Data-driven methods—surrogate models for adsorption energies and barriers (e.g., graph neural networks), learned electronic/structural descriptors, and generative design coupled with Bayesian/active learning and automated experimentation—enable fast screening and rational optimization, accelerating catalysts for CO₂ reduction, ammonia synthesis, fuel-cell reactions, and selective oxidations. -### Why PaddleMaterials? - -- ✅ **Rich Pretrained Models** - 50+ pretrained models ready for inference -- ✅ **Multi-Task Integration** - Unified framework across PP, SG, MLIP, MLES, SE -- ✅ **Domestic Hardware Support** - Full support for MetaX GPUs and NVIDIA GPUs -- ✅ **PaddlePaddle Ecosystem** - Seamless integration with PaddlePaddle tools -- ✅ **Production-Ready** - Distributed training, mixed precision, checkpoint recovery - ---- +**Amorphous materials**, have no detectable crystal structure.its characteristic of atomic arrangement is more like liguid and has no long-range periodicity. It has attracted increasing attention duo to its broad applciations in optoelectronics, catalysis, and batteries. Its structure-property relationship is highly complex and sensitive to disorder, making it challenging to predict and design. ## 📣 News +🔥 **2025.09.25**: The **MetaX** has supported all models of multiple tasks including MLIP, MLES, PP, SG, SE. Welcome to run PaddleMaterials on MetaX chips. To experience the MetaX chip in a public cloud environment, please refer to this [PaddleMaterials_MetaX_README](./docs/MetaX/PaddleMaterials_MetaX_README.md). Pleare reference to [SupportedHardwareList](./docs/multi_device.md) for more multi-hardware adaption information. ---- +🔥 **2025.09.12**: The **Suzhou Laboratory** has established a novel model DiffNMR based on PaddleMaterials, a novel end-to-end framework that leverages a conditional discrete diffusion model for de novo molecular structure elucidation from NMR spectra. For more information, please refer to [DiffNMR](./research/DiffNMR/README.md). -## 📑 Tasks +🔥 **2025.07.01**: The **Suzhou Laboratory** has established a novel framework based on PaddleMaterials, combining an active learning workflow with conditional-diffusion-based structure generation, thereby achieving unprecedented expansion of two-dimensional material databases. For more information, please refer to [ML2DDB](./research/ML2DDB/README.md). -| Task | Description | Link | -|------|-------------|------| -| **Property Prediction (PP)** | Predict formation energy, band gap, elastic properties | [README](property_prediction/README.md) | -| **Structure Generation (SG)** | Generate new crystal structures with diffusion models | [README](structure_generation/README.md) | -| **Interatomic Potential (IP)** | DFT-accurate potentials for molecular dynamics | [README](interatomic_potentials/README.md) | -| **Electronic Structure (ES)** | Predict electronic structure properties | [README](electronic_structure/README.md) | -| **Spectrum Elucidation (SE)** | Reconstruct molecular structures from NMR spectra | [README](spectrum_elucidation/README.md) | - ---- +## 📑 Task +- [MLIP-Machine Learning Interatomic Potential](interatomic_potentials/README.md) +- [MLES-Machine Learning Electronic Structure](electronic_structure/README.md) +- [PP-Property Prediction](property_prediction/README.md) +- [SG-Structure Generation](structure_generation/README.md) +- [SE-Spectrum Elucidation](spectrum_elucidation/README.md) ## 🔧 Installation -Please refer to the installation [document](Install.md) for your hardware environment. See [SupportedHardwareList](./docs/multi_device.md) for more multi-hardware adaptation information. +Please refer to the installation [document](Install.md) on your harware environment reference to [SupportedHardwareList](./docs/multi_device.md). ---- ## ⚡ Get Started -### Property Prediction - -Predict material formation energy using a pretrained MEGNet model: - -```bash -python property_prediction/predict.py \ - --model_name='megnet_mp2018_train_60k_e_form' \ - --weights_name='best.pdparams' \ - --cif_file_path='./property_prediction/example_data/cifs/' \ - --save_path='result.csv' -``` - -### Structure Generation - -Generate novel crystal structures: - -```bash -python structure_generation/predict.py \ - --model_name='mattergen_mp20' \ - --num_structures=100 \ - --save_path='generated_structures/' -``` - -### Interatomic Potentials - -Run molecular dynamics with ML potentials: - +PaddleMaterials offers multiple built-in models that can be directly used for inference. Taking the `megnet_mp2018_train_60k_e_form` model as an example (a MEGNet model trained on the MP2018 dataset for material formation energy prediction), use the following command for inference: ```bash -python interatomic_potentials/run_md.py - --model_name='mattersim_1M' - --structure_path='input.cif' - --temperature=300 +python property_prediction/predict.py --model_name='megnet_mp2018_train_60k_e_form' --weights_name='best.pdparams' --cif_file_path='./property_prediction/example_data/cifs/' --save_path='result.csv' ``` ---- - -### Train Your Own Model - -For training and fine-tuning, refer to the [documentation](get_started.md). - -### Contribute to PaddleMaterials - -For developer, please refer to [architecture](docs/ARCHITECTURE_ch.md). - ---- - -## 🎯 Available Pretrained Models - -| Task | Models | Dataset | -|------|--------|---------| -| **Property Prediction** | MEGNet, iComformer, DimeNet++ | MP2018, MP2024, JARVIS | -| **Structure Generation** | MatterGen, DiffCSP | MP20, ALEX | -| **Interatomic Potentials** | CHGNet, MatterSim | MPTRJ | -| **Electronic Structure** | InfGCN | Custom datasets | - -Full model list: See [MODEL_REGISTRY](ppmat/models/__init__.py) - ---- - -## ⭐️ Star History - -[![Star History Chart](https://api.star-history.com/svg?repos=PaddlePaddle/PaddleMaterials&type=date&legend=top-left)](https://www.star-history.com/#PaddlePaddle/PaddleMaterilas&type=date&legend=top-left) - ---- + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterDescription
--model_nameName of the built-in model
--weights_nameWeights file name
--cif_file_pathPath to CIF files for prediction
--save_pathPath to save prediction results
+ +For more information on how to use PaddleMaterials to train and fine tune a model, please refer to the [documentation](get_started.md). ## 👩‍👩‍👧‍👦 Cooperation

- - - + + +

---- - ## 👩‍👩‍👧‍👦 Community -Join the PaddleMaterials WeChat group to discuss with us! +Join PaddleMaterials WeChat group to disscuss with us!

---- +## 🔄 Feedback + +We sincerely invite you to spare a moment from your busy schedule to share your [feedback](https://paddle.wjx.cn/vm/rXyQwB2.aspx#). ## 📜 License PaddleMaterials is licensed under the [Apache License 2.0](LICENSE). ---- ## 🎓 Citation -```bibtex -@misc{paddlematerials2025, - title={PaddleMaterials, a deep learning toolkit based on PaddlePaddle for material science.}, - author={PaddleMaterials Contributors}, - howpublished = {\url{https://github.com/PaddlePaddle/PaddleMaterials}}, - year={2025} -} -``` ---- + @misc{paddlematerials2025, + title={PaddleMaterials, a deep learning toolkit based on PaddlePaddle for material science.}, + author={PaddleMaterials Contributors}, + howpublished = {\url{https://github.com/PaddlePaddle/PaddleMaterials}}, + year={2025} + } -## Acknowledgements -This repository references code from the following projects: +## Acknowledgements -[PaddleScience](https://github.com/PaddlePaddle/PaddleScience) | -[Matgl](https://github.com/materialsvirtuallab/matgl) | -[CDVAE](https://github.com/txie-93/cdvae) | -[DiffCSP](https://github.com/jiaor17/DiffCSP) | -[MatterGen](https://github.com/microsoft/mattergen) | -[MatterSim](https://github.com/microsoft/mattersim) | -[CHGNet](https://github.com/CederGroupHub/chgnet) | -[AIRS](https://github.com/divelab/AIRS) \ No newline at end of file +This repository references the code from the following repositories: +[PaddleScience](https://github.com/PaddlePaddle/PaddleScience), +[Matgl](https://github.com/materialsvirtuallab/matgl), +[CDVAE](https://github.com/txie-93/cdvae), +[DiffCSP](https://github.com/jiaor17/DiffCSP), +[MatterGen](https://github.com/microsoft/mattergen), +[MatterSim](https://github.com/microsoft/mattersim), +[CHGNet](https://github.com/CederGroupHub/chgnet), +[AIRS](https://github.com/divelab/AIRS), +etc. + + diff --git a/docs/MetaX.png b/docs/MetaX.png new file mode 100644 index 0000000000000000000000000000000000000000..585a224e5d37d39c42053d509247e0bf259db6b9 GIT binary patch literal 129498 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

4!^UuYM=a);&Hqi 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 wp}qAhPWrFUptSY|-{2e}$yEj+}*( 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 literal 0 HcmV?d00001 diff --git a/docs/zhonghua.jpeg b/docs/zhonghua.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..015845f070935c16d6dead7197cdfbdfc7384016 GIT binary patch literal 45349 zcmdqJcT`hf*De~QcLC`LNL8vd0V$Cm(p3bcmrzAOdKX9(6p$)ikRk}8w1_mRp(7w5 zT|i0#N)04P38dZa`;~jnc)vf+xc{6n?t-0cviHv3bFI0aIp;Iyg8YNL2D)ghZ=?^R zpa6jkfgcbV3A&>f;q?#%x_cKS1pnLUPTgw012lf6vk=zYpqXYF)MpIIVfG)66P_j{w`$0m$mDCjfYJX4q+bAwjQc=^; z($O<80w*+G1YMw@q`W{yNli@!+?pZ=I1Zv>qh`ONphLr9=0YnHcuDbDMk$@>KlMGF z=93sPCD))>dIm0T9$r3i3CXM1q?A=|sH&;o)V-~zZ(wL-Z1KR-%G$=(&duH9q30tn z@8FQou<(e;CvneT#3v-aOv=p4&dJStonKJ)uDs%X<%f?|pBoyRnp?iKw)OV)4-5`{ z9UhsQo|&DS|FN)$M6GZ9`n|cey@Ngcb98)iiaR_1D;Ll!{~;Fe`ajCW2FP`Rii(no z_ODzN7sCGv&PGLjMS+H0$Bfn`kV8cA8QrCSGD_=v=tY&xF`TYJlMGy9%1CkSU(x<0 z+5eefvHzbW`)|SiU%8e*x}XdHYLpj%QKF;-Mv4k()U?!p8!a8}zZ%_tHimyS#=njE zzZ)6&5(?lufQxB>UuJq*`u{%mf4oCp29!&Uya-~VqyUtOk_`j~5ea2US3!R__&3u< z&l6%?&&{UIr(Mi_z8`nO{62=)8TZ;7iW?9&uJ_YOs`1<1MLyU74Q1?-K`qup8YRzR z42Vyf>S4aoMyPf1)W(b(;w=sLwP$Y@S1sA-r(7SIXf>41Ado@xTLj+Tnfm+ZCkjrg zr`863@X?A+zi0^i=Im9IoiCnVp)nm9J5Wg+5}Pm>K4gZKPdRR12>Mp#Uy;T$O3nOB zmtV##uF+lOgP8jt>kbb5t>{O%s3`wPq(9Hj$+qv)=FiJUfe%NN4x1VWkS@c6)+vR~ zf1I@Rpzkqio~-WMbxw0u`1Dwtsu71BKjQvAbec3?g1H|fI%wStWyVcVH@~d-3V( z-}>XcWKv6(4Gj$8~U^yaS-1?B~P>wR6d0aderG=YHiSf8E9%w^{tO%8tjVx z^~rEWvf#EB=B)tRGi+)&nB({?+7c@|;3QGlMYOgq~nVqRC^d~hW%-FDl4>$Zw zdJVYV$vk_oq9d&qi@b#&@_wGZevmqJ@C@Q@{pSi^E820Ui=OacO4G+vx}q5CRdu_z z(X{g0h=;zmLnWvRF;ek4jz@F;Xt;89(L0xGu_*4WdH&UqrhIJsyBytXeIR`uS}Mw2 z$O~+);U}I6FC)9cV<*!pqIK3G*b-SYiNgHM5kg!RD%ctg&4BNo%fD!}pJ0nfI=l?N zJB{?(ud8&<7~l&sl03R>v=)2^%bnP0O8>~3B!Ly*cmmCPf9q7$S}~Jd?H#Y!8oQ}8 zNIVTh^-B6|jrg7n@-sAWp?03^T5 z5)>4%F;A-pozLBf5MYW7IGTz%g~5)}zXi6|Npniiy=n2y`|0g<^LNwRpUGpa_uHoH zF2%Di-oY612FLO;6s8o$_@GN-VJ(OOM1pnLqG#H^JGLZ&Fu*}S;9TW`Qk@L z+Gtes$l_0yf8YmnY5HmxZpc8_;9D#RdeogX+lTTCk`Y?2g!U(JoaD}e+@ty*Ft5hk z)JQU@2T;kb=;Pj`t8Xv-Ym@$!&PG}i`b-ABP^pHq?rN*I*e_jk;+{J#Ope0$7MNEo;eab zGhn|iYJyS|P6LzP3k)r~sQji%qWw$yas2Q?Wn18IZ&QCJr$bTIt>FQv6RgK-UEe|2{-L1E{qpt`F}JeF?{pQX`12*WUXT>Lpv&eq+uG9%Rm&KWp-t zkTf(Z>80_>vObnMa8T~vS9Fk(W62#e2DaL8@hn+Y@Wh44@496xAWFj)ao)><_@_|QwItX+# z)93smPN6iy`a~bcfgEM!z1}p_)V}LE>);lEm|-~h3EM0xmyQ>0bbprHgG*Dd{)0n@w z_!RpuTtrkN7VtxNvC?ZTaUEVtXL;P`4$@)x{1(Thhm3K#GDD}6h!wH(%t-iec0?p% zt?Z3bbfW6NmhP-Inn! zol8MNuk`--4XyA@sGYl!E_+~Mr1%MDQaFr|?lb`4N(C8|0Yj-0pBgk) z-7_XEHz9?uga~zjZ4K52%z9}2;dS-W=lZ4L9|vYsNl%5bhrr_PsF#~kNew4(Dbyd> zs}hgq++Qt`-eV*Ex4Jbm7Q6Pzpak1!0P#y3`d~$XyrT25q;AAvSTQvj^aVjGfJ>hn zeeAc&7JrnN@Q!!z@PBwp3}Ue4xsx!CAIo|l7l`s{*H|KI3FlOP^5Ua0Nt}DoldHBA zHpd_Tlkye4!2Gd4WE@7gq)NJ1(qD4CSpnM?c;K=-64V&Srhh#Z6)Cj$F)+{vZy2qX zyJ-DlssDyTZfa6y=2y0PQJgJLHOq5$RvN^I5t2R3197Id8cznDC~mKwtNWa1)?iE6 zm3s&>(udU~21o1!p0SThh+0!Cycusl@VkCvI3aDAbsq_n^YHldCNooiWJ{67=g19} z-mk@hH0WE7LdhqlpR>Gpcq+@|T&r9tbNz}YZGn~Hw5Fd+vGkcQ?j4rZ9tX!VI^mL0 zqNJj_6|GTyp3i;Uj7)TfROJd%`uUsQDSs?pRF27cevhastp8=-5DTC6$B9D-=_CMQ zKWV{9=_+Rykg8RTG2%>!5DeJeC(Spnmn=8IG_x_;dxbyhLvO@tPZ6Jy zcvSoS7bW$&+TyLJJH#p>UqZ}2-Sr-k<;+i`P-RL1G4+c&gBazHLLofRz7mieiJBn7 zit;i2jDrtwFcR%<^klB6oyyjJlnRLcFdTN-%E&S37UxM!FiI-eRQDaLX)YgN2yFO) zms`~T7d9dC)L%=m-eHer>@L3W%umw?#jK=jM6-d9nF-t5{c=sJuIDw4GYiFFWOd~| zi#!?5)eNOV*VgjAw85k^JN(HaF|To3vprp)dsC)0c968@5urKocwI0-O{>8X@eFX} z{hvYDRqP!Zd%CXIBWB>?F~yV5o2N%CRbSPQXVhN_3QWO7tgSb{w@7=gRlYSWw=cJv zG0N1(cr8f3#vUC4($_^XJ!Q98RoF4WfLy02Dd= zHhp!#rOG%s?pJ%mvi;Fnv8vuB>q)`ufHkK$R^9W#jI5&ahL$Ps%!ovWEb~KKo>Zss z>>0oA+epvY=M#JEj;v2xM_}qF}P-6Z-(-Ng+ z(Z85RJzgEDwNVP)>DYIu+QjJx(7HHzG9gKw{h{?ib7~PE;8>IJLu=EGX#eEa>h6G9 zre>Du{^1eG+KZZ!nnJrH&#imy0G{{VAq|}7DlXNoCMrvZ`#e^ZW;QW&oXlRlQ9bc^ z>BeU`d&VoeCj<%jBKQYn@WRl*&4XAufxTH@^OK*xV)V82*1WX8WCij!ocDHED4}l9 zNeHV!?`o=(EXKjmt+8=N&_~$vVocf|V^6VCHg+-14k0$seEI4^&F2jFO zcgntEqc~yCUA=l-&7V4dc*QFUz?&pK3BuxOmuJ$X9_NvMkKU#G6p$|^m^+9@SZ_L( z1zl`F5D(W-D8iElJP=y-sb3BXH=ClFF>xonxCN};l$Q7Y9GHIVF#gegXiny}-#pZJ zta_s7tiN7aa^)O0|4E5w#ONX=pOZlz{x7WCWDgRl=GYufs&}5$;!F&!43e%EHRpMx zUH??~-7zgH)8|jI>iG50fOKkoZ%ckV*)W2(eTir9nV&@Q71t{L?+vqCF}!-wwJ~^K z=;&fdvExvhb8xOhj~gsNu|v?cIWS$fP;j9x9e~27^u0|~e(0gw~DOwbwRKD1rQ``Bj#JMfM|48jXy~&hFMS7KhQti|MG0j zOJxp`VS$WK?jbHY9xktRXob`0K30!w{EgdKz$hU?qM*cI;3k7eiBCv|yXQY~KvXG0 z`x3Fo3L}Hc1QD4x4|?{-1^jhSU?h4I;20Uy?|)91f*m=IL7V3{@(ApCBs~DySC7xi z0rTEoK=iGPHo)>uCXo0TNV=N9F;SXIG6<3hL+* zIY9RU9V(Y&oe9z%>AwfWbCUd+RnnlN1{q`^3p2MQv_nU@K086Dz$`9_AEZ%?>i72F zxWE+JD2EvW4B=-1Xgi1t3 zWVt@)B6A54E4ECa!Kwog-cbyq=hVUg31M;=^AEG^PBxz@4N8|E3BdGPKeiQ9__-eY zrH7aZC>;MmYL{Hx;ELksPz={gg~*PcrcnD2XZALK=7fJJeWLOew7K#|`UhzQ@(G*> zl^pY0FGeB3??x~hBpNP#6A#Fc;!j+6H5}Ce*L8o@T zdH>_~mFC8#RM&W(`LeRBAlBWnn>lWDcr}J1N%bhBlCS%n0s*@PDc7sY#DDHoy04OeHyDJmK}B%w zD0niQ5V#(7I-}yKbE?ro&&S$&$!JnUr}x7eYjoCm1)iPM_gPmwZ;&Ev%ho z-k8uB-==+dp=+Yf`^%d;o6E|d=Ax&6UIonYzh>xvuq&0}AGS~UwO2!#Tk?yFLz3Rq zr>qC^4(fZC5X78>$e_1HB_t{Xpl8jTTOaOPPVKp0Tv@SSYIW@K$T3SQOhG29eN_ok z7cEdJ;IcNjKQaTJhP4IzU`8!`x!5dkB` zhQV-bz*BMB)ej3y)_nimb~E0}BF95BmToOpn#1g9AXC-zfrlHvZvcyNGo|ynz(weD zEAY!`gLe_Sw`Md=QPLl38kZH9_x(KcXW2wk+<(1(mi3+K(2$cril7}>XoR+@^ZJj`dpD*$m(qmbGWogHMn#~ z`tT2lA+*-VNdO013x2z!S`c-kI+$OpsXwE=YAJ=*!x=EQ7bJ^)=E1?Tk4!EsWk34(KH+gV!3hcp%q)Shl8FF4Pt0jF0SHygDEOR$6V z`Lj567Q<1=*{yAvqGG`YmA1`f(DK)+3k^SIoL?cEtL3HyGUiBMSJ^ZrF`H}e(<=!N zag~*@UbBx^XWTzwCE72A7x)(SUTJ7%bNu#sh__`y@z*VF{}JQIDwUt33x7jrgAawE z)1sN`?`%swLPD8pDy2pusn~j`tT+A9rC3VjM89e5&8ld19HMN|=gB{BWuT`u zm0r3-9~HDz|aLLe<+n^;aA`B+5NINASLif4G(n&Xn96vAKlENc;=0x)+F z+*OHsjP5!O0@F3$6SmlBC;#JQ#pr`3v;1PMaI1RCEo4}JGjYApvr8J8zNmY$g%v_G zuJLpUA>w^Iw7gDm{(cfkd&?cY)BzbTWp|T1<1*F7Z*3WB^f9a39$hb%U~Aif>2jTN zod(nn)O=JnErRpYSj5G}DzeZG+=T!dvp0ly7{V(*YU@nPTN{lDB7^L{q}eBLA3(=Z zS05yz?lTT^yA9QxTaIE-FBvtfI{Q6Vwp(pL$?=}0+~i@plio#h$czG zo4o#XJlC-hk$rZ8Gc2P$%v!5$+HCsZlo-3iUn0*>$mcxSR2!cPEEKRD`4`Zd1Nhv7 zCI~ z8T`+*ub+#L&*#Z8=Eg@`ffT$}Q~`!nIW%SEFH<90l_y%S!oj#etZBCpcZfQ{2(xLE zY&Y#&w=!s-_%2t)K5=(jo&5QX_*bq}9(#{Z^Gdo(A%VKqPNcTLvF0?ej^$ zz~y0CZ{aM~eC<)JNz{E_Pn3;hyPI^x2HZ1T`7eEr4OiPS;Kce9G$&2~MJ(}W2cV1! zOvp0h3(Bq6GcI>~=ecE+sUXs8tNS_Ea^jn106k?Lg(%p}6uwz$21UB zN-RH35;T03yMMaQLC}l|eQh;&hBlIv8Ga3)y#^r^V0B&eu%25`I)WDNF4CU{_kMlg zW?g;7_M~1+sO*UY$jjmz7wEzf8_D*g57r+a!Zn zm57Ci&82<>j)Ij85}O-JfUT90K_I{qFe~-hd9)-#7pnhG{ zL^ge^IEi40^T(T!CJQF^K4MJ<+Ty>Yf}acBPB5Nl5cP(5A!f=r-o;y|-M*;({aez5 z>x}K0#le^*)GFbUB#M+5S{to47kbxkWMqA>VeHZqcke7;)`ruMypleY-J%8XY7_gW zQm}1WuBpZ8NfLn#_Y5mUVo<^~^o^kqLf%j6GRkWvmzut1YzJMomq3``;l z5aYVUahs@?9_jQ;(K@pgbD?_k{<3=gANj7wtG$(a{gN$!kz-nOW;`w>vhIQOHIv+- z#Rq1PEEvX&buqY~L_60AegR=>8tvqN&|+4#%l#x8&GhxNw0Kj!yD&1lv97Wu+vjFL zaGsQ0`Hbkdi8*8GUx**;{SeL$H;kkqHhlnXfw#7t`(3<0ytpWB>o%>!cIz`;rg9ie z_PzC>t(Zfm-e3NWnimU0Gh@gg`>A6gMqCvcWP;&pdfc2W_(sHbl&h?wz@|J`wuR-h ze$tK!dhn>5ch#&S^3WmQ(pcaG?06NP5B3mRWV}l()#hH@g^Q%Kd6{tLcKV63QFknq zs9fR_e9+CMTU?q4`p9{-?0L0uZ%kBd_PZG*1>8uBeuKY5(8i6SCTJq=@%!(^NDz8F ze|zaaRCsJfg}{1h`3xbD2!v0`*}5lyP!^7ij5q3>vDfbn9S}Kj6hI1sh<6}^CiuYw z_5$$#dZy`4!y)(FTPPVc35i>wBqG3GcY{&#@dWX@pWB~$s(kojQm0@KYs?etDpUFS z(?^zsgfk8x9V$7-_xKB@t19cs)A)mvNn-6jiSc#`O9vHOhyBOJm@@l$iuGyP3c19Q z);@=N^RG2Gs*ta*d(dL={eq(N1lwxUI$Via+iWO*R+~@ta6x1tzCANQgXL*R-R3$h z)sG|+?T8Ief%DYQgxcpODsf-)<%qPx?mN@7^(MwW>)yJ_Dg)or78t(z3up6TXw@rN zy9K?KKJ=$>>b(-1#A;h{@+hIVGwUQ0dmm#uBt(hJ*tpo|Te~n6D0=CB^E``iVI~=L z^};p&tdu8kv-J?%M&>mxo7eA30iS}YMxBc7dz{mXNK&owgNnv1NaU}{58E@TdTn0B zq5VoUz(n#9RIx+x1mCqz^IhW@{Xu)90@`nio!Mo2?7iKC8}wgRDuvzN)&MaBqFFl& zZdXE2@SS$fT|wVwg)z5{`iitLpR_;xx)}AkkCND}UW-URWyDsW7+~i6e>~7SuC0i# z)*h66`~o`mhy=+GW%(QO2pVpcLF6E*cJwiMjEDx&-!wnI-mGu(K({eo5!wtTi)*GDH} zR5jFvROKyBcK2RIixA^N?y|9rc6u5$L9%Ikmz>-(S5rAdKmekk zMV45XvqlEd;%*FBUFF;HNkp1M4fjfI+<3O1N(ggI2!zAOl9u}TaA#Q_*=SWyEWo$vW+e(70>yq8|)=G?<)q!(R(D>+t{c z)#zZ*Kux6{03jtziXCJ?h&f`AZkeXDT&ttT=;|M@!?ldefZM_PbRZ_slT4p}-#X8R z)};M~Z^5^A#r$qomyTrY)4|)oYh^cR2TDL4+}H~|hu^)erquM#+~O=6!ygWxJ^dq^ zdh6heXGJ8z$8_gxpO&X@W;ufH9X2RQdJD)jBToFW zo@ho?PvtgpPZR9Cv)EiSn*EGb`++TTGw{^sDAHH7qiR@_`>&(-a;0{Y_Xuwl;%PK}4jU>ETM$_^bX zsc%kqsfmD(&UZMEOzD2O>$?fLv$Zf*)Sxl&h+B=_&peV@I^<)QNVFTqbZ-<{4T(cg zhv2Oc)9Xu0-~*Ayu))p3I;KQy7F(XVL0NIhnrmId zF(2h~iixfUG(R2&b74+Cj{Pj z#~RE+2D!ZPWi&7Lm{s|z+^N}-Hg@GpTej0rXm3|n@#c4ah0KuVn2+(h&z1b0 z+)5qUR-=1+>BA#e%R1M0(@VQ(NYju@+Em^FB`n_TPFqgSKD8|S`cc>JfAZ37Qom^2 zN3zqW7+0mC^o8j{n7Tx8!Kk5UA?ZRmyMIpj8ZX>W?|)@n`S{bIesjY$n%{FD`*yfj>EI$L$M3?T?MP)G3o_~~8DIv+Bs(-zfv zW1lXbesq{oDg|U}@q+{M6+O^7P}JX?7pTe6jTWdkthjuch1d2TowGijW*p>)N@RRJ z#$atIF;pYfAA(_hajd0}C5$GwkMWJ8P@bB8nMNX>57$46&Fe9Y6z!)yIf|*MnfRT6 zG#!E`!>HV6#BdN4Z-`k{;=p1g*QuGwFHbj~eb*dHITR&`pDG2_nf14v0;p&CkFpVK zAON>MFd!%mb+evJKmn!bp-v!!c;1nC*Vkx?9AH}5S}Z`RrdYw*?zVr)mr>Cx%fQM1 zt7gOw_8)a7(mwlBVi-_WAXpizZkH323d%B+ImJky^F9o->Z2Kt+k zm81X}sqp`&+yiRq#&GnDKUkwE{b@7|wfcf2`w2V$3}7G|RK}FX@v`$-mqtJs(`QfeHOx-KpB)DD5} z!#~&!tM!Un-~BR~{qaUvn3cKndU@{Lk1?9vb z;;-Pr@r_Z;67p|0>YI`lpsw^N6|-SbiG!67Cnu(V7U@p9CX`e1sbtSMbM@qfDp{huQdIU&*e~|e%viazgL=WhPC>fLn+hg?s*yb^)OGGkB zpV^dzkOLpNS#KW@*x@9AJQE;;eh31zk3qpPz{)TeTM6Ml5S!tHaGVsn=4Dm1a;JEh ziGS_wces|@bB}`u6<*S)AHx^y2mr|$TNZJ1-5O_roZz)ja6zJ-`_vqAY(nWy4xBHo zv+ME2+8T_d8S$+3wLdU`UU7N@W~e?VPSurnP3;{#WDrEHT(gm9;GIzzG*TNrhHo$+ zs?rxW2b&QWNwg8719Q_&J)M)j<|zGNUGtAiJlm+&+-v)T1v!{;* zZ%K5e0z&=oDOxWmKy(OnF+74%Xi~h}grdnMXVo7)$ztv| zV(Qb5(OopaU7^w8xVSYm{}A7$a|W-)Uxn6lWvG(}*?Nlcjys>OGsk_Uny-NM7)OV% z!7k%gds?8hSe6_Vk8DWw>&-ml&e&s-u)>RV-!)#is)N>02tC+CVDur>%HXHPpvhxI zq9E7w!5#tZ!aP7NA$4N`vfCf>8i4`$ z6(Jn!P{HQY_ZZce%IR$4MepCY$d<3_M1N{b_q%WC98PC*Z4e-2Lf}&e3%aI_vj`9W z3)@egLw#$1KRbzBA9lo!xLZ4XWCGaOSUR+=bykkphSxt*D(+>_09cO>8RXp#<6UX# zVNI~hblBqZV@;HE?lXvtWO}yVVx+#z+5YySbf3|)lB|+jK+l?QhtW)+BpO|4jyPX`?CiU3AZru*{VMs z$Nl8^7!7+rC>kzR6x^XUD{TK{x$(>fOr=d1A-N_W>r3EW8-*G9!z(D!s;6pwCep0K z528PGuxwygo5Fic($mNwnkIibui(2}^}eaP#Q!O4;V3O7U;kwK@yzdlM5YdS9a(rWqo( zlL#}!3Mh>c9_&-hhIv>jHBqyIvs<;A6TGo}v8%PSQ&%9mB=>4rnr7PNS6wuFtV^p) z!PYp(vS_~eQ`GOc7?c(V-g}aLq<3p!^dw7QN#HB*z1jNchjB(w&iJW zZomlA=|9{^Ne3@s7#&G6i0>VVb7)V24AKh+h#=uCGAPxI3}O^I;Q^A6dMF4%XqXHd zdIS`hrsJ7llOkAo66*$F@R}++H*vi9F38J$7$w*pvhZeIzdl^D5AxEER4JcOJokHF zy|LcwMaI%Yz6bY%+=SQF;7f~ul+QX$G5nA@O%I`-bQ*6bu3UZ}ni;W~Q0}fjGaW1D zWewLIDRq($%TOod0>Ziwt`1m80ZB+(lHE)FU`@XR|vayK- zojsRedIQBW?gT>YU|xSSTmTlZ0hB@vE{Y6FpC5uX4>VOApg*Fbv~=&2hMS82+)9ek zb;;Vx=z8NS7*l2WX2cu7a(|Zs>C@141dH;rqye!en)Ur7ZDAl$Rei4++x0YeaUvTN z)2tBX-)t&p5N>+6ra#3Z)^6$WQ~B~N{`3y1xEix`@|jqI@cKyb!SbU*8ytq#oKLO$ zVUI;hKN*r>M`ky|KGAM0ebr1N4#VRSKJtr7Yw;zRlA%?W3T%9l>Pxw!cA|vV&B@|@ zkFH0{n)%T$GF&}ErARLKQ~NFkNT)q7uh@Ur+~K-@poFzvGw3-;g>b=D61$l4^#=1V zF+*KvxJ~`#f>7Z6^7M!iLB&AG#{xKk!{;CDuYPSAY(k2P{oU~U4WE6DdDi2R=KC5E z>)G@+S(4-B`(m55&`{_oxJjU-L8kaxXA@=%OFf?`i*|l)6nslPbwY51B2D`QnU1+4Z+b z(e<4CEDT7B?ZQnAKB`9uC}yC*we&opO{%~a!~M?3^E^K&OZ!vG_=YkV-&g3lV&bOu zyURTN#DWO#Qh!t+-+%cZ+YVc=4?py76h(c+#Yzub&AI%RqSWfsjF1V}53oF>V=h2x zU)vFCvhFt76{3h(AA(+)mdNZ8WWF)o-@-A({OX(8M?*P2weQcRJ`Rm^Dx@@TOr>~y z$dmFjPfIvp-9ut14Ty!&tTAgb9G0zf!do2`p$KdnXUamfI;tPcziFhFEb90J4ecQ=<4E7b3w1QhfYVdd}R zD&b2DOFN4>-?+{D9%hPHb$m z6|APB?)$_VU&1IqtX+0DT?V~W^l6j7e8XKIN1$$LDcDCz+lQ{ojMtZKFf|BJWOWZ~ z?KUS!I}F<(;onN6b0#M3S8>HY#L$P(Weq|A!vA){ph80P-EGH+MF4WYN z$I=PM#W`^InJzU9mCzp9c7QRv-CeYkHT!a6t*`YwK4@kRiz-16t!L~E==i;9+?qgU z-Ed>#3z7oPvm2_?1{5u38BL+;yV?shG&=8%a~1SiS=lTudb#u3R7i~|6=gnEV;O+? zf{{)Ul%y9$K-v}r%zu=$RMvAL>6cAv<34X*|882P-&*A-u?-;+{Q5veA6EN~hssfy zpNqP`)LPBsa8Ab^TJykF&G}w1FWAk0fpM**uht%=nk1vrDy!UoD;MkiSfceyet)2@ zAo8^6hx?xyKXjrwxK2 z_-4z=2Vxn)1aFSpt4xsDM`9`yYWF>+L)KK)3 z9&i|SQ#VOe06Bgr8>4_JIZ+~JM(g+^$)IE*<|Xr48P^UI^vwhGG+lXa@7l)^!$iE* zqoh~2#?{sf2zj_osX3nX<{E@3M;n1{8g{0e)YGnPz1JE zV;&9pTSg<1_n&1nbBFb{5qn?ZC>gR2Qg6xn+gx(qB ziQ5d~@e-JRrye@y6|l%V6ApP@+t`|i?lNcXj80iQb5XNs!HxloG+t<5^M(Q`wb-C& z158+h^hDrV`xyK9qQNHd!lrpcgy=X;bhGUx_smOIw?OcME@px?v693Ytu=QHkDKS7 z)4tf!#o;~wX*;Z?`TO!`Js!oeK!1gl9EB8j7M&r9rWD8WA~^KDV&?B;>!vordi-tg z)t1nSzL(C#x8@rWMsQg|pLkssAF-U>Wz<&qb#O60CdzsX2*s30cSkl!g8=XmIeZ}n zH{tz|C5w|%jO<`WAQybylu7nb2AFV@vQ#GFe$~Pjvb8mSyjFUy?QPe;!e?1=k|obO zOx6%j=buO>9qpz{5j71yDA_x_AAUf$rrT;N9IsC$s6$iMoV|xWRDM@$QoXor>PdVD zWX-`$&eur6=vh|aWwZ3vMC)byL`!<)$>(+XyL>0dX$WzKZ5bE<^7)8pzB!he) z=}J3Ja+&sMHAgb&G4B2G@~aN{E872D*T|`K`SsSELD=;RJ>)&Osbx<-96Q~=jpgX! z!`u2yCHt6EYgySotiQ3<&wIsxMU$E{Inwa`4dGXu`N=WTnA2_u6WARV$9<9UdBaqQ ziRVmct(8ZAON-P~BPBVTyjM>%Zdar)rv^RQq#wL^s`@bNc_lassXvs|rA^?(xvXCX zBh!dc4yxWDl*P9*_?f?}Z6X`G}6(QQ4;J&DG zpXQ!gf3&S6o1yk2Kj#4BT>Ty@f$Jm1^zhAMei$Eg0oK@XX1pDW>NNbiQ8fI1`#wu~ zq1;lGJ1AsjjUqRI_2|W#KQ%52IsZJQgc4`Iy4Q9u^>J?VWL9f4+$xMD875wYc==Lm zM{4>3+Vf*b)y=$V-LpYVdQz7(bU^5Go$P*TE@SGA^}WTSlsCEamea`sH&dRD?Bc(Q zk!S{=D3)wxArtz6@POcq@l8+bV2o~Q^VnI7dr`3BK^e{Q-YCsx_$==|org??4S@{8 zL!hHpLXEIE^u|<0($F9u``1OipXD`*6@8yh76@+4%E zrpcfqi3orgqkd8X)Z1CFkU`DL5W=$do$KdR+HP6%Wn0+TI@yoRvpFpGey~IRc9$~u6r-jU z7FfFo1pWLaI>de;qNC5%_ZU6fxW{Ehr zEhnK!pg(4CeKyk`lgB>GBEk8O{XCk3hh!PEwdgM!xI&wXAa|iZpw#{#=%k?h^yCeD z?>tZ2=HAaA)6Ix@>aU;|IYrtIAC}VkS@V6){i$Etq-aVHd5MvZpqG=%w&rpqC!0=z zvT{cWS~M$xV|RcH#zvxvfUk9R{JuRUULa-;VyyJJcBR)jUM7!GBWvl&p&C3%Wtj^o z{VkXUI^_7l;eqmQzOScKfY{5VW<`oY16oRv*7P5{sB#!RNn`6~@w+hJ5MPI`j4A=7 z=9~J&qCed>byR+1Gg2+JF+F&10x&wyqfpfF)W^;Xo+v|D^w%#sQI9WZ2Lvz<)wePC zD{Snm{0`_6#e)-loGUP{+?ucfp_fmZ!bk>#5uMqvM*(Q2xq?&7)J7go+y|WX*{KHC z+v&eHF;MHd1`xYfu+;Ip$-K>d9~S(s$jSa0r@8fqLu_!UbiGvgOq}yPO_kb!`=5x% zw7XITYs#qDbgCQHIdKZGuHfU$p&dqR!Yy@=JF<|mQ4 zJ6FrD9Bc50U5UH8iN5hA@O!T1wX7x(VVqbH^7R=!P|cIDH{pLDhIX$)!)@zrunk7+2vthAWz z=d~}udfyYCYtu+6do@P#PPn%T?+Qq3Rjd(^zPpa&|Da&eLF0<nzfYuMRbL|3im@w(TwaZ6CH;sb zG=*Np9@i#3^!ar);jD}u*3BYl^7w%yfn&(h)3yK6dBH{@rY)tL^(`gkVuuj>`ltc5 ztzWfH%r>wDt((u!yL~3qP zhF2m>0I36_7*$|USHY`el?GP0iP>Eo+c26g9_?js6La=3hKDc3B*!{m*G+DYEF9vx zMc>bY{va9>o;Jc3z$Z^Sa3$;ZE<#D6IP>2TVoRG>UuAf>Cd5<4ioFgsw^wJ2gHYn$ z^|v8XfFVSsKJnKkgUs_Qi?GjH+o&(+++uk531pp+^=oyP%XQaso?d6G?Visclk?@0 z7?cpVHt(nvEgd=q&fhXuq&iP9UkIB$vK}b#s*{LHPVn*o*4(wq0E_O7Br}aRvdkv+ zpyN4>28V9G?G5OOA8|cGizLmN4*#H}?~l0RdFa8{+dD^SD8K(BP77Y)Jj3Fxqi+Ka z&KvB(K(X+P(*=9SBE_LosP(y4!anDxpj8cNZTsJ6ZC88YJJ8xH@E!usx8jW!o+4P* z-5T{90YgKzEJQB9&FRmb>x&%jef=8QwM~$O4}AKOj+WWwEbylz?F(is!zGTLDo-FR zzl45ts5~DPt2OsooB(72tME&1T{6>)q5sZ#{tWOJyFcfe3PvoMQ4>BWC)?Q2P%z$A z_Yi-QN##lVNpcP$zk4c4qHkKWjRs@>JZ1KcBmrJlw&~9527EF}=E( zW|MSwPo;k_*TPKemwOkUWK^QlcggWiFLOvc0X$Yx76SZZ0Ve1t;MSnO8z&)h{)87Y z(qGb0iKe`i$`P%Ejl4QwKz!NqUYgoR?p3(mTt(HeoG^AhwT!n+g&hgybQ+t}i+oM|@^rPu;{Jf zfny6HdGqF574DE_;e6iiXPZuR9`=HoLnld39wiH@Mw*56Sj|q9D{$RHa3eVW=IA1n z_MaewlFNp<%4+uDpLZVbK2KeFGcH;$t+_3A0E`ul;NuNHk}3PjknaeV3^dH`cwx^1kei!I$o!GKdE>LM{4*}@ta$t?jGlIS@ z(hvE@9ny>%`9&qhhZuexbV&&(vZjixm>fO2Y@%4sz6@@g6Y{qdVRLB?YMve>Z(sb!kH0#*cw?8$PcoER3|M za#l4O)81PV_Y~BQ{&R=s=ECa2p1AGV>YrjhsSp9+xo*z*&ojoBn)i=y06HK_g^=oC z5^wxqOA8d0`Ldh4@3L;5&;QRjB=*pf_dN@3clbnc*!6-|jt`&h3Lo8nz0D^pas3fn40WpVyL4ZW z^rWzw_ms+*_vC6zL_7&jmrA^(vBjk7DVR=y$f29xSf8R(Hd*io=W|7;E59!sv(G+h zPF;5nP7NR{9~C9V3mIgn-oTLnjT=DIy#s6~0RT8)-sL2$h!J%*EAPRNc>5E)M^o;cK74`i81ai<-g#O z%jQeV$;KKo+(hTSNd+}~pOQlpMvGoQ*8nCpNpXQrTfyQ@}OXt*q9q+7d8uB$h+&wx4y5g_Pvjk@6~xStCY+=tE_$ zYwL3kKX46@$Plp2Z>${QbVLThSH%C}%~a(;fG_|5WsYqs7Pb(&25Lg0*?OG~crV-& z@(P=a6UGQ5OEOSITVWZO&KS;&)PC~D)s+j{Pa;{<<57WQOFQx(Wdii)VZg+`nGN*1 z9!;Q2`dQdtscJwl82ugW1|slh@txinkJm&|tM920QA#&|>2ik*jx`Yppml)80XPISz#9_eYd9?eQF2$IaQF0% z^=|ddF?Q(8%3v8ibO?Nch|_|)^;?FV;1dQX_t0z?6Pe`?BwO(8-1nhb*n8;s?Hmqx z-n)Pewxbb&#Xr&#HY3aet>%!%;en`<116IDkDtlf-P6Rp1TNMJcx*yZMA(lDup4mc z!W@A7=+UB2*kW5j5fG_DH$#`VMPtzF!}QB(#e#mv^KN&}^2+#Mv*X=yDLeTDiHqaK zoQFROUj%^b_MFo(swk0T22?rdVfdsCZ)|@C-B?hu`Qd!iAyS8+e)(%vxb=o}chc1C zac0tveZoUMmMylWw9Slu(9*scy8c$!C97jSzj$qgx@mc?59Z<`#6e{hmPMbFuGP~j z={BkwF-+Y#C)>%3Canl2#oga!Z4{~+ylkr9B4wjGoYH3gaM|=;%hfBJ!6>5Qi9A(d zCR1v8N#-pJZUsaR=pDq`krYXi)?SB!b567DEz^a~ISf2WQv64X{lC-=+2~h^6>G=m zA&MCepG8O4p(TF)bSEW z2*aQ5k7FcmU*URLiBa=_f3r950YqQs;{|D^H)5x~srFW}xG##+lD*TR*#we$#3Xkj zue&M)SlrgWV+^sCf;e`J>_TJP0Yu8Z$m+03diqyZPp?f&i^k6+k*94d11rv5iLkkk zL?~%3KXB&SV~sDu#!eGUun0DWzk11FGD+Bnw{l$V%}iAnq+Fj~%$rVbk40zW{pJ6o zNm%IbLAKDf(Fi-%C~ym6qXHl%pDnE_5;LWm2Prf^0%T~L4)!u~cE^`;=n+OtGH*0{ z5-8Bzu&8iZG>`TCNx&&N_y9+MBK&Ia1EF24E_CZ1O67G5$V}OG)z9SMA9S+Zp*aNu zbwUf-+}lZo0|+Qub=w&~Bjhi9?-NZ4fEXi=H^>OJ_CCI2G7a<^Jf)pxI* z(ii7SqQLQW!$_gSP!xUP(oojmARQF(bXCKF&?Cd9q{F9KPQNss$f`bG#XF>6XZ=oj zBXetmo6yI&qWM5E7y(!Bd-d==PwnTCPcH?AsHBg~dfHuL;JW=npUESYZ+qcvXs+VE zbhD{$1i*1IwGS#pI53dA%$oO=~ zh^dXWG!uH<)BBpzF5H!pz^$#>y}Eih zPz6{0oua=o8+v^+SlQ=EJmcs;QwUG5`QintQ4U1p2`L4Ri>?kL6!Q;Q8L$-rrw{(n zrkEYHdKDHeFI%ce50Z&lESEn?RwkN<71RLLngYUxZ0>2YAw>#j(`FPcmQnVynrE)0 zr)t<)XfdCS_N9R*Oc6lt7gYXBgb81c_-#{H52^D%|2|kgNUPhAKmSd728$k zLJ9or)9o6v&Z0G>EFA}Ud4m4tL)Z5R@`SCSPDf`Im!E(yOMvQj4RiN4DC#P3S@7-L zO;g)zzq}`_FSp0q8uSyk1yAod5@34@NyJJG#FM#H-9GO!_|1US!r6m~y1@(zq@e&b zL-UNbwBU$#voeLoNoC|~wa`v4VTw4T3PAj%DdlGDVkeY4WV-wceq1g?|~lc<4tw6aOp15N@V^PoM` zldvXOEwr|?7nd32x`VAjbb4dnjy*uEzX&_tX13=6g?aXB8# z-pP_1GzaI0x)Yc2cC9(HzD2f>@-gOZch>OB)ra(9dH>|s|KX+i0uWMdI&jmUuP%HK z?@l)f0@XnyxPL|R+1#6FGFp4p~I~Y+E zMHJN5JHbW*MVsSO(j4dAE|=~Ks9n>{7u}@$xhd-s)KA~QEzwPB37$fK^)QcSdT8?= zf}Fq~JBd2wZ5ILrIuuv90>1|ddPW%WSznNcN zx?4+1o2Ou!_QLWcqU7le!3p=X2xU81Ius8C{0S>=B9~-N;nAiJola-#e1J$(e8okU zUBZ+G@$(p-ct1!cLG8}A>uLF3nNDMylU{nx^E`V2`2HY8;zqrLjWk*w{$}2yx(d?t zNF?2qJ!5ga{!Gu8w)T+)F9$%ison-#Usl{W%w69GsRtym>9m$o5V`i^iH68i4cI{o0QEac@xy@id!pK zv>L=#04X;c2o@bn$`!SG`K@=g-<%<W+bHgN0j=6`3y#HlZC@9O}{SFOVF!Q&?zU? zh-q%J(nE%~7k{Nnmo_#0R^*XBh8X+jpM&0s3HnZn5c~+8LZ;-j}Df=EM^?Ste9kLZYk#K^-WxI;onLapds zwN*S7%ahZIeIt`Rq`n@F=5!%M_kE%K!?TS8_q512m6La6>G5p+l444dFCDQR?Z%9Q zVUAm}ui5! zJ%}T@j}+J{9l)}62f|4I>LJSfvvX9m`){qQYChK&-Id7B%qMRt3|rl1-i|v5*n&Ky zPI9cwe|Qi6x=+OWxVL)87ssiVEn6H)kC7RKR6l$iC;KT`0B{oQTujht&G@HgbCu`L zwG>8U0Vk&3I}m**=`*-UEGsu|VJ^+GzTF-A6KrWmT$p3sylUC^jm}2KVgKEHX9V!U zJ3)tj0b|YL2o&J!J%0cLo>TZZ`1~A@oKXM|>y(PDStVHvBlex}4w}Xt4x_eN(Mb$s zYD%B>dDHw|-Q295lfRwpE3d3d2mvEgLjLhVq(K6vQXfe)6}C3R)_CH446{1pzmMRVo5(sq8)Hdn|6PR*H!6Uu^gZr(qe z6#{(S0QXH4Nv;77#Vvw}9!DCXN8nty>Um`zp4NpaHk=^}4b3eHQNubpmFntFB3OZz`K4P)R2v)?dy)K*_tyeM;BBsdf*)tl<&>nhuf%$2h?&@c_!;j(3VIG~h8whz&F%sE zqHQE*Mtm_ii?$(EwD|LCA6fdz8((7iN#=(Ny(!6=;of}-@wckHId0It;t&z-(2+eD zb#epJIWAYfPx6luw6(@XE2Q~Edsj#y&FKm;;<|$|ov!{O+RRAC;IZ#l-2Yo4um^F8 zb>AkzQe!(L!PnFZssLP&x5B68eY4AH#&&hia{$f>Sc0ECHh~{YW;|b5y>I64? zF#4m*Lr)uus0}>!+0xfcXlU>JR0;Gg`9^ArIt54I^^(TxiPvDEt<`d)-q)i3;j*(c za{?j*nzuED$F7qD+vof@hNar;VQG*FWR%iFY`qe<))tgiW7AW5KRg58f7b!rx*Weh z%6WA*S!oL;^}eV{yW&jMF{zpI6)Z?Mk0^du z++c#;Fg<^pm*k`O&}97F;yNd6?T;1V~;5X|5`GI(l-fr^$?JN z32H|^nSXTROx5Dy!~ru*w<5?nKJUIuD#QcjSQ~G!fPmysF%XHl)_nEg^Rbdja#k(#yU_3)gYU-rF|0f!=Qp^*nyr~jC2FiF_|4$TCo z!WaP%tbkPsNjHEngil0b_=*qT+Qb5d-05XA$Tjr#U^4oX%9LE?^WQJn#k9ZSkNbct zr45GyoC!y#Bq;kffx!`U?U@E%WuiP^tg%~szZw$OZ^KYK%?)e*l{#=Z zj4C$Cnqo9fDCB#QQr`XtlYCc=B3`D>#~3|JDD#qW?20`_8%PAb3d+ z4w$FQUEjiz9p*S%riFHzA`Y(j?tb01-471l86tS2F1OGa%+$TC*Lw;WJBTK;oM#&3 zpH_NWz@vukqE)IdjbB;fr{YzO$rw*xWb20(u3K(crt@<*eQ`>tyI}g1lCoYiCoAt; zXJmW=IBCjw&nMzG$l7I5@m+GIy~(tV!>)3$CEVn^FL5cGQ?C5`<>P9i399{FSq9dN z9-!m;ro@UHzkJ)D5y3g@pyOr6)hhS?NZzaYL0P?rPlV{cA`n}vW-8Gvq7q_!-J01t zkXVS0ec3W4b<52#^p`AZp;V-h!Mnj_wsrEvnvvwJ*E)@X0%=_h*zE|9$}+Q@ibeMUNAyn+RC+ z@~5T-0E^x;g9pS4l!p2*3_RBo)wmp-4jHABD-I<7$W4#qX#qdu`}FZA{+Z-;vYa9OPT{P&tva?sqpO zDL$()PSV^@)Rmez}b5A?qMDwb($mENeO-)%%6?O zE1YoVhLm`;r?!wVeCSESBl&*kolT}1we(6GL8{3!FjMd?5OgPi;@A=bGTQ)daH0y3 z?zzc`uDxu!@)`8*Bz*qrhpinztAeD%j*heV26W{~^bP*SPo+lw(ql%;YyGogId|P0 zz03;y=A~zgAd=&No>a2&DK%1T&8bEtgFZF=t z)@79weM^_Kd%VOP3SHF;J^Y=02rQjYo8`*XUBpHw=D6{hIzbnG-#O zwCvtsg)ny#p?ZNx{)`l`fZ6cRVXkOv(>({D<_ErFmTV;948eYzrxE_JSXL_cjA{Sm zhOnF(PO9!J=Q6aHS8p0S zX0;^s5{I6|7)GUh@_j%&rlUq3^H0PO!qX3Wmq&_|>;wp9Du1JSqS$JO);iNv%`WjD zrW$8U+I_qFnfH6?7XnS$Z*-FjU2v>3LVtDc4y?SKshk;UZm5qILcpJmFK#FB^WWkT zy6Wqm%+q{10bcxZG-LubbE$_my;V74bZXn~EmI3Awp1(>3WPI+Wy1qguA}0m_HMoK{C|V(?Sg!=EVmTuI_~Gh6rIC*J<2#NY zKRgZiJ^rklfMN~p_t9m~zw&Q+Gr0T=1EafE4@foYnr)q@aJ~V7MmPTy#NF8Uf~=sg z^OkvDpaOx>m23_5YQ;)oWylXmmF2LjP6C3% zdI=t?KVyyp*Td?G5Fh}1BI?!HbRHBVyE#T)(>5EzADKL76B!#ASwywaboXzdvhBJTw( zpUn%mD^|M#IkR+(o~v}9&Xd=bx779z3p(S_@LMr-DcoxMNRB<*68YPD5A`afseQAm zM?_g(6VGtNb*mFxGkO044c%Ob zK9>5Bez;+P9LOV|)m1XL&mEUa(WHk*J@h#O1MWWBPMY9YxJJB)q@uyH_s@`NsIyHg z?&NTVXT-L5ccYnUmbt>gzdzg>ZsPeOt0r|eqvO5|n^b*sq3LzruV7T~#gR5?Uqk+h z(R+J&kr>MotYI^@Z7*RWI+sRC8l4E=Af=&T!R6o8y^oJ&VS)_i-lr6JD4#3v7j(IU zVgmGZ5B@^Q`uuYJZyTBh^jq9d8;2TcZpK1WTS9BfCFBZ*D@ej_IDU?!Ah6-*C!x;G+n zY0ylCpnh0lMtXY2jlUC|Duf2%KY35p!9gdWo8-|Oa$Kc^C&yn_&aDJ)9o5|Wy&pJw zkvP4X=Ai2iilL_h@BCOf`$L)ecZ)jZ0L%|--IR1XWc{O)5W+GUelJ+%b{jhIh$V41 z@mq!#^QO$DXVcV>mBZS|6%C!B3~|?bzs61;f(A8XfySa}_Xp@u9l1Fqq}Bp@!d4c` z`M)RZIb%g0vuJg})!xP;Uf-Gl3`fJg>MYv#X|A0lGfwA1LYzHgLE@1xmzHHsg1aj0 zoa{WQeJQAp@PIFyC}R}WSiO$Bp5rtn&iLj(yqr_4p&t3W5mC{hvoCIIhdN<% z4O<!1n@KmCjvk0@QJ2BLOEEH4rWW1cgc`N?#{Lxg7?Hoiz>R*2Z*a#;8y2Ml#e@ zV$%V4haL^Yc~(flbeorFs-1#CD`A{0h%svicQQ+ft4xXgx``LAGbj%Y{!5OphHQ#= zhHpGr>McEJg$NKJR_vXw z;riHD@yw$Qpl2~-OrfEn+QA48jolKgEub=ObJV+Bv68kJrmdTYnA&+8(?R z^L=5-Fz2i9C7!ksSz_!7i;-x%#Y zi25tAX*!T712Aot-XGKDjQ67L{iJ5KS-;y~r_T*b{`k{xA=Fi7-%M61_AU+Gb}NBf z?UX}5^ay7Tz8q^zCR$vTYU_U@?v`aiCqGZirCRA>_SMk})o3Fs1_l)E4HO9tP(0kI zk_aj&Dwj!~+S zQwBytFG(`_zTW03TGMt;a&}f{*)7jLxL%=FJcN7Nc9AlMe2*+u{hoL@Apnuu2FnKI zCCcr`pKxr@#rkWQWec2HgMZiN@0{#We|;l1!TE*)_&q{ORM=oVkoH}rsv4n?f_Cfa z)p$qEmb0cbduv)|&o%UNo5$r)%p#OmuDxlB1LV%7opsX`)(lvANkTS-9&E{bN9QvC zLU}kX^PPxz6^BVP1%1LyeOSLV3t)+#vk@@vEFafU{=^1@$- zB+Clv421OAGd}*h{->Hi7V+zpFE4g%TZY&aFfQmYptEZi{M}MZf$d!&5fXB zcKlhQ(GwY(D{y{xgd>UCiao!;3cxK#;Mt*h^-`;??+f=ms5NqgEa-O~2#&8m{O*42 zyFmd2DBr8UH3**rJN#-5&PP#v_&(Wi31O=}DA@iTPa4g}>F~Rk!AWQ~7wU(T`eSns z?RhJJ9_bBS_H2a3Hsq0j%~#A{b0oAW4-pS_o!bPOY+Q}Tz8T5Y(0y2!+Gbm>8{`wH z333K4M|FW3l0F6m!HcqA&P$HvEz7Ab8A?8Rb~eIPGa@M1_2bPQ0?6<$s{=?Vwg|_F zn_%R88=G)q6ZYbQQ!X&g1%GXgn&nNn*%o<(gD>768CHtz3Ctr6z@W^iqW9DL3-!&`WZ-434U?uO z!QVUw&<{{YEO`4QvvlLnWDb#jM}1Q#Da+vUWAi8RuJL1c zICC^I9y8~g^53a(MiND|3n52(yXDP5 zfd(9Ds3_3~dguvZL6LUr!9(Sb`fG39z}WoCk`RTT!uF}eqH%rqnI9Sw94iui`{%h+ zBL2fT><(qbXq8s2&1XWgoZg@Figk;tbN6g8`Oez#)we8n`_u<-B3)0QFKpOR_dddP zsIK~QIXhx?r~m%3*g8CfN2*b~h?{@J5*Y+DXJOV*&KT+!N9OZ24I)cN@V&C_#bYM_ ztkizrC!*2hd!&HDI>10RVc4FX`;D&(5{5K_##!V<$Hpib?|K#_MGXsg{rs)`%5FqzyA^d3Z4N@E_M6M;f-y)%2=f}}8SGy}`%N9@EGO>O$ zryhO0e>62buJinx>#M7ftX~}#>sS1NAWfL##tO6-)F9m~64@w3>-_+o`8ait-b6LX z)sIYLkB|4cgTKLj(^nM8S_QIysTj>onMmzz$iGfq15Wg78o}DN>i)_N)UF-++y2WA zE!0syOK8XA5d`k{Nq1@|?qOYP$PI_pVg;IkueA@E6VXH3r3V_Mx70djZhAi zG8(O^r}qt4sp-i4y19cQ!jU9@Kd>0FgvcU2miN+_+TF|C=!EQq8B|j3KB#gKGQkpJ zx(UknY1XuW@+^q<1V#8)IjbV~3d_+G2I-n?J@Y3kRqGOS)tJZ{rfL%UEhmM@_^4z$ zpy~c9ih8!5E1*&-vcMZvZen5RKdn_fF zJCnL!iW>(bU*#}ugOU;9%;<_<5HfMYEj#07Yvl1-x8z}QdnR=+llo|RV3V2HwWeVt zRHNd$9{bT>8%T`^pUZvJs#8m9**0c(FnjmMCso0(B%}8!9-E;#s}YOrjJPxb!IvBi z7TjM$hV|P4Y_r<$J8waLOG|TobNb1NQ6w>CQMx((lPByW5@KB>ctbo9y!dCmeK1y> z5+ndyqM(Lk+RXTPtZ=_1*ctItCn(69dV$XO!1sd}Nl2|`e^y{mQ7F_udPpJauhYMF zA0mMC-Xa4x0gLX+8t9Kt1Y>IRpQARk?1Si1IE&P%p2&*dAvOy-dpObkH_!Bw77B6>LKS!+nu|CXM9{EyNAAh zEzM(lVI4@&0Jz@txcOGmEEuMNlCB7ai_jb`sBgULZ1_5%xJhx}xG9N?_d|N9dC%+2 z5QXw&pJ|Z$#?m<$o#>8iRzn$?X6+uAtmD(P?@gVw^xfSYcp@$%|E6DyDagAgZv?c= zq&_PIbM{`!-aICp-v>uu5K#$uC0TCYc~5P_bnjw73B3||hr5Gf3kq;y_`&v<+h{Jp zCV+@;%6<*MRb)K$u2+xu5xg`Fl1W$)hje<>F!PS?3kKzu-c2i}t2oEpF-n~ZVJqCA zgSt^f<`D>QPq&9{5kwh%QRttkvI}kd`JSp0)mOD!VNc?~&(zGoQGwP%Rlo-aDJVc6 zm6#8QemukfQ2pIe%-Z6&U!zm>&x1CCvVnO#1kXJn*4CK_nU?_dI8DfvMK>zuw@p<` znF(f?rE|rtbN&idA^yzEy*|vw>3qk2t;L_CM~UvpqLS?a)J-HV{4PbwK?ca7>8G}O z`n+VU(H!SQDv(dc=GYdFW{$<;y4W_bP)v^n{B=sUVZkHi|C zzn4Xt-jI8;JRWjfkU~sw{X5zk-@!ZiEmGGfGW<1q2$cxF+(!mfZNz&^=G{dHJ&!V) zo%0qJ`a4f)X?3VAn8HE*rG%Wo)?>8P!HkFI&&JP<*iPc)rIDWW<-axz?F&*zN7?aT zz31n(%TC!lb39EQM)o9AINj{&IUkxoWncJ!Q9x$Ib^_dcx4P0}cO|a6c>Ng+_sq+m z4IT14R&*yAdX`X%5U~$)JRBLAFu}TcnF?HIR>wQQRxH-RSh+^wAR(- z?oD&6&}5H2e_~{qm&JbFy^;%T&qBIez-Gc9h66@YYKVBsvbL|FN0mW;ANM+o!A-#D zUUoJ?pMG}!iV?yteq|{bvJ?*O1IMw|+r%PoMvRdZkr?tSU>bAjoIO2N81us2BA)O@ zv11oAf+>3+ipjGZ3#A6ZUK6Z@lCBIDdrr)6P=`-#5JA{vBDdxP(2)>j2Szev;Rs=m z=4AQrGyX3z;?8&F7qcBNA6I%ev;t8sZ+0No~GQVoH2aQ1wB^> zZ!g#X&^)9|3qG6sxe|_#{f?sx)-%JFC=rK``e^z2eg9)Y9+MX!`l)dzrJ=sP9Ff2w z`AT3{*@%keJAVW>`d>ag;E(Y>{or?Gp__%HMd~!pO*M!T{*2Rk?CD`dUuYD6<;4&u z{)LO_@rN-kb>`-NfLip{IRyciJ6-w~`Sys6~o{ac3-!X4k05l=zE+x9vW zBdf}|;?HFYZ{BphJC?fE1Dpz7b;$;R%5!_>ZZ~&*#Zpi06FXj$#|pa~9?lHE@RHRm zux6F~-RfSv%b&j$WP{`zHj-d8QWGnCx0{{W0L0u+UaUN0Z5Ea~n`)@7MSmZYr*J3e zNm}Opanopa3j0Yec*cCdTjo!8Ez6pPpp+cDcCswuGmAP!3O`n(=nO!`$vn9Y=GoBG*fSu_i+@e zbUXHgkZ1Kp{O9c6<*+e~fQ04!!Wdc3cR*&N7iY))J^W9or=U)+CR8&fY{6>9B^cuDFh;oPy=Ast^!Uwcb zPSKT_oidnLX!w?WC_Kjfl+x8SC`kW+Kf{|-`qS@mHxsS~Sk8qQdU;&W6OFlpBUk&`Qvy zKd`}T#hdUC>yvaLb)4B|?X73ge66(}A4!V(885577)kkUkPK;B!VS^CflVYT7a#qO ztyhHh=%Ca+`89XRh@b&!a8*H!`BG7ycY4)sPamJ>;4U6j7u(qBils8rrfM57>*NvR z9u$9=MeMpfk$W0l(%jsVJ|@Kc_4i8(e)Awr>4@Sp>LznQ0r>~i00mlRFmfS|J@oWJ zu-mvyThptlkXkc~XADUiCMLw*&bzUKEjAJ@&d0A&{~8BbYYV=E4D`I&komnhItBBDE>&3N^--<__t4uR z*Xpg;R;`{%>T8o|@6}8^VD;N8#D6EnsLT&v(7N35ux{ zv~_L3D$&pLhR=lr1o_Z^$XDik{@|Ld#aHtvYlB>Y2)Vz-gE&G7pZ2xdWQ)W=C_DrF zSPGO=4p2J9OqSH9?*j8F2~)n(@LP*(JV|yW1>0<0)^~hquDuCGCT~vw54LvFa@Oz!S*F9!objEONy2YiXeX84B%G{`~>g?=X)Qa7gu z%E-{VD6@&CJ{?N&eM9!Tdyv@{c;3Fx8ZQM#TsC0w@81+jiQqhgsRk{QCMu>7$4}!j zkm9TUz$sCduT-KsL14=2PR4(R>_{kDzE_DkeE>{}-n${KQp@MPN|hA$DwSZ#k6cOd zCbkj#JOED@IYjL>f9+`h<-O~NfGyi!9wGC3CP-YXkkwm*eKuV4TYwr?`-d=V@2#{s zPvQwfO1_}BvhhRB${>NwQi~0$PALdEdhM2T=m$gvCAF7X=ysJA9{a=XZ9rmAO4SOd z%*m%`oT0_B{?4hzKDnyG8iRmOFEFa`*=EgBGQ334ljGNv$Mns0rjbXEN1+Huh0ntf zo;3LnBVq=!Jd3c+qH~w&U=Dc3yLKjTyQUjlV@QzuC4oL^J7xbp!y$wB64nVRshac? zlH0mUhbmvRLKl>V>e0zafy>uumQ6sQ_;zcim&$Bqut4fhXqEbz>?ghUe(KO6Qtti7 zG#tOJgpGAKx+j)1Hk${nRl?}H7-z;REL9f7U9SSCSFA!vx?je3sK`b3$}`06c;P>R zfpF|A!O%V!Qa|s0F#bU2%Un9-c(%8@t8`n9D~y24_+8uX@Hf56?Me*nh^-TI4a4IDh82O%{g-Xhhr> zI_WS*NR0sy@d|naj?2g97muIbcS?k(@@)@hQm3?-n7&LvMG`x5Y4V^XF8z=}Q4lrY z)Gi?Kw-s5}akvTH*{X)GCw6qS^9w;pZ4SA@YK8t(&Ci-lzK=cZWkKQ4Zs`WLW9U-J z#;dbj5Ms<*AGSL9L?=dGXXH=e@k)5Pt8p=X$>f3Y=d72v)7uC(=ZxcQ1#IGONahlZ zP59WaSy0;lMsxDSy;5%nRcfSnqs&y&4&SzbBL{Lh_REM1npCA2<9 zwkP=1TEQ(7HrbY2F)8SIBpN_j^pG39&)axnJsb8Nh|TVM63&-15u{9(?Bm%|7?0_Y zuT37U50Bnh_9!W#0V!j!y$Om4QH&B$n@uY8A+VsfaQrDu@M7;xishokn1H;Tmplsx zNl~4b>|Y>A3f!pCot$*@Wj=P3#l~F9@@Zo4qK)N{r@V6UvoA8_N%>#z(!`4x;IZe8 z!Im>jP=Ot{A?P5rpH0&jM3bI^x*5(}e5vHj?+7wdwIrSzlQ7rv>;;OImvKHx>NP=w zwv)+RfXN2t3SthfQCSFQAA*lm$$853B)5|Dx&fL5$IN$e&(q~!%H5S1%(5^DnVOC_ z4XvZm;&H4~>Oz?!=58g>s{P_jAZmO&<*$ZGRggBx3y8`38DZb*=1)hpxH# zUKqrk*WR!p(=I=wWl=qz7Ax@eriHpc@q24Um-Wju5%v5p$xz?Lnx@~L=qDZ)y|eKX z`FG*H@WpeLfxOmKK(41k~t*a?jj>k4fBy>#DRH%H-E(E`2DpCXCje1~t1 zJ2pN-^eUDQ-iGbYl1i*R^9&(=vbLnEY<7R7PG;N~-`NH4@?mG^Geohc!o*6Mk|abZ z3f|w`Kaxke)D359F$tEEjaOri+leSoDlp`;H632s^CAq~p|sIME?kad^Kb&eJtFwQ zdNvui1_ypF%}sU78vdIOgO7&G$-e$6CHxt<2NUcRS=4q0Dw#D}FHGX#hW6L~;Z3BT zXcCX7`XP_jTJ4#j&-%;ZB{-LYkIl%f*>bSF4Yo9#IG6%%aNx6HVPz&+=UVZoQcNp| zXlb-Wtns~Q*EFG^nfkLXvf|Wymb|=884JssaGr9^bCgEBg5f{J9qHV=CSfzjKKa*E zjx-w~EimMHyllqa(kVDuNbtGyHQ9^QEdmjYB%tMhU7>XgAy0ynVi~QWskvsc*{>@Pl}VCGQOgv+xJ+I zxN~-=Q~3^vA3mJr3NBDd)CiMnMzht}(4i}k`vW#aY*g)vTck|MWFZDR+@+j(&XEMM z*w^1CcE6H9AAaJq0dS@|peQTD92Wzw{kc(6y_^OgI@hzpM$GFS?i%+w#+C7i)Vtz+ z;k3;gCYQw+Z=No)8MP;ARRJY}8KNB7$A4^`Iz2sB6eyH>T(@d@yb=xURetIrQxQIU zbK1)SET=|;kU{Xo@$7&f>#Ft@;6$nIz!co*l*Fp$cb0Q&Z4MgWB5~#)%Pq95GWA3s zzSQi5H+A2tV)$CodBqU+#yJ~r%A-K{AFilDZ;q8!i;nuW%J`>-wDU32uhR*(Sq40s z2Pb0ix9>uTb#%=k4pSjDjx3c3X6;M+pxdF#kQXoUM6Y2VHP)ZjjMpr4FFZrD-P&O2 zP$$KLawhSP-@6@y1YP>6UE>uVJmc6KmC#^}5XWN?7nlLr>fLw4Nq3_15XRd-GA||= z4`pbx+@D@^)PC&F%;y2MiT`M}iB|i?Lhf{+rjb2@5;9855V^4b+X{OcE{mIn(JC0D zT30R|u$j3lx+rGhL6e0G;#4!C<)@IVMErg^PW@6U%_(`w_v&%P0JES`0jzd#M1f-3 z`ELCoRxRj^AImN`jTh_9&ZUj}Hwsh|hXUM->ni!$y^LS4$bQF0jWfFRyYozzR~@kK zuY&GDWNu#t6IsmeqY>Mu6zJsc%O-Ivp^c^JjvWII394ygL}3zV0$oax_;$1vo|&EH zzgrJ-97zoD2cchZCz_Ai-RLMCcwC(|LX3%qMG{J zb&rCg6lo$&K`DY%X@ax}N*54RIz*+0UZoS1-US4tMmo|Wy#;LWXor`n!x!rq=eX&MHa3{&TJ=^20dJ0c2biDG;M08Rk4UoU_x z3y<{|V2V)?@K?cAv=rD@ZKG0pt`yHbw?3#jG&9wy9`s~;Q{$Jc>89fPDGQ=HpCtA} z#Fy{P8Q*zP{r&>h4G%$3q{zTx^HUag?|LJ%y)*Rq0RRBFph&s?Id2O*-Em&jAs=iQv^l1*VHeI6?%7 zY0#8FtSzxwwkIg5ncZ5WXJ!eozSmHvgX%LicM7wf8jrzf-OL`JvpyH#Cv>H40i|v#Xlx z?@IWD4Sq&oS#J5z@#wf3QW6j{w|Qc2wc8!z684I=b#&daQ!J%#=jO#Xc+Vo!mI4hS z514kCLlL=;k`PaPm;_P z$>R|6>xQN+SskrK&MfLHBu&J<=DIzSgoMnPRoaJT9#K*JUu%<+Kz~vH=?4#&A*5mR zeu0>Xa+j>Q%cNUH_JOdddjCA`Agy%RNud&2fXpoINDJX;W)x9r zGhvs)GF(zHE(0h{!x?X#<>Z*`N2BG>qU2Q`-I&D0gL#1#DlLTvz9*A(g)X?7OD^Q zJjoYTQ$(Bdjn?5Z?;r=PjfQoV+`85zZ7ASS8}FiRzd*`W-c)NiO5;N_d{tIX3gVlbSL z92gMf$eZcWN9Om|YTNf={Ib@=Z6(~budH!d0W4wbQ|po`EEY~BeZM|~$~~4uJs&qj zpbB{JG8_bP2+IoCThDFlK;La3o^;;%aV~45S>Vq*Zh;dn z=jIa1r~U9{iP0oW!))-)an}dO@=3*qZ9=WmfukV$K!vT5MenIC=^ck?HX*U0m--)P z&wlC|Wh+Sw?+nFVCuclsUs)vZGPOf*n1UG)hlSSi_;s_iX7qX9ry#r$|YxVOBjP@V> z&;a{taV?AbJh9nHVW80v&8>?OV!l9gBup6WDtrRY(@k)O@Ie{8n~f*FNWV*QRkWn| zbYj>v$FAcVC%rusz_A3L?!a|NmQL!n-dD{td+?o zBJk&J!z)~I(s_otuOfngz7hW7B@*&y*A$`zmXU=Ne7QmYI*26z$#(_6MG(P}n@vc9 zubFtqwkbmL_b%8Fm# z=wW9eY@fgPe-CAVz-VSwn)5mo}OcL0Jyxci4`OlsuL<&EnC~+wT=Y#9o zf)K9xfddOv1W_zfbxQ6v{!vZ2*k;W(%l0AG}T_VDD( zR524(M^DmIQ9dDouq^HFYf+z{albok!)nu9BgFq&B(J>?=wZDD$6T00>4w}!?9c(- z!7a_kv)o$DS#Q*u6JI8?kbf4ffsLf|2b8X^ip*35x?>Gi;5#TB93M#71w^9m7?tRN zWoj1BoHB^PlP~h;?E*j3fja7Y_7A=5;wsD-%XkiHw`Y@tHbC82eDU+BFOZdBfho95 z$SWU|VsdGxBBblWxJ?&K%Vh3w%7 zYkIq0nP+BC+NCe$>p^eUU$_w2I;OWSx$x)5`K6YOQm5*BzepQtF}6ARx)Nn6p;TP%tnD6DKS z0*Nlb#X=Tmu}mHz$A$rs5;Vc6qjIs~4c&$ejj;;&gY&l&pLtYMZhI`UDyeC+yhwXW z)o|gM8~XOqBW2S3IUh@8YMX^lcqK5y}U_TE6Gt={C; zR*%h#$fXNCZ{%lA0H;8!;5*wm9Smw0g6YC-1ba4kWYHh$>Q92IZIWI>=!cg~2JrdU zX=5KKmE8;5d9)wDfaZ&}ZbYZJA&$NmY^E{E8k5L&Eq{1pkF*64~N%(>6be$6!g zBG*ryS)J|IW6Bz>HV+@3VCvxeVSs>l=>!mrz933sg`=^#&LO@<5za^Uod@LL7%tpt~`Aj4z#LvLE~gj+I47w@2m#i z?ugI>n{->VO&Ou`nsN!ei*bI+651!x^mObcx6Y%e-(6JvVaCMri>Ou-A}~XTC5<2q zaBLk4Tw@L%$t{!Ch{>bbX2bQSgDg&JxdC=daSiSs!@98>_Y*<>dl;qfO@ypJ=Y5;or6H%+owv}T{$l+bn&oL2UN1k*?l(?K*F9R3ddYNO*7bhRUL)B9Sni;}s%$~lQZMe8@e zzihY#*L=|mMCvMQ8D}1>TNG(2$rS?~{DUL>Y|(yx13r$z%j!#6tWQ5AJkQIE0kj35 z^Y7Ana~9?XDezALV*>+MUDlTLm(tua-CT#H`v~ng?{U`g^zrD6?Qp%^pkyEUj(J9M zWhYzYA~Wz70fpHO?9-||X%CtZC^bR^ zd#Mwee&-X!5o1)oUYDWOseX5K?kdlr*-U;yCcD{mI^^y+sxxAzio8$d74 zI{;Qu)Y1B=4riT&nN9GtaKAU7skbGir|2xG>c&VdypEoJ-;(h~A$*F+h9$+s2gxY{ zKIPsfI_b0exay&Ya8I6zdKxYr?!-o&r^a_z zpor~lM=u8X3*~&uA;e~GrJ&q3J%shuLX?dPtlu@0lhA!uzngxb#f886uOfkGA3_Ky z66gx*d!?fODH4Dl#i`#+aC3VR+TJT?$x+Rhht_QHlg7*WZZD~J`XQt7uzSJ|)=;Kt zCCA;p%W=L)PFwCefz>cN*!=Gm9`%0Yd!X}$GH|$!0>M(@-Px7RK3;Ku0^uQSVBFx> zzYYnVMI`Rh%ktmxx!K18cg;ng&Qu^d4 z>Lm&#ML+jzQ^G;6zrafch$@WKxWB0PF$chRda<9!F+7XE{&>tLU?^u3yo6x0Hn%K| zEHVQL(qG_dtaX%hu#VQC+)_Y_)6d?!#@oIBnOz=OS=c%jt3^T)JW^qo^hBw2w9oO3 zlXbel^uw^H%*ukrQl^}0I6*s0{vER!3oecv*li%llL6Gj%2=B&Y95iJ=}b)rF0ap; zMhP0+Ul3MCEN>%v=eff45C%n~+HXzj6Zq2&4iy{;&(C>?w+LM2^^ruHTUY+S3JCg=d;0=?$1j%pRMeIl;9>`b3Ox+Uc{H}Kda z`%QAP?sS=blfhwW~&52t>zn+`>w1s#lxH`Tg{>C=D80zSr%=)4(Zp-Xpy^C`Nw~z8lKliLu zpMRZALfl$AIkV*6S6!qq=65qY9R@U0y0j4-$hr-_;Smd5(d_#Ti5ssf8=JD7pBU-! z&4iTmria|%;@ACJD!g|8(A+WavIAWGBo>ne?i3}MRTvmYayGO!HKm*UnR-N4dCG8y zUD4o`P72c?sY3>84gQm_XqRWsd{{mncF7w!2)Z69M6g%F7DXLt)tNJg3e|*FCGQqg z*S#?8;@k3x{=kQx;oy_^DN}=5a(r?@dkg=9FgZFe-82rMW_#7h$&%l|q}SIwIFQEs zYNu$G{J~pA&en|FP(4k}_(Z9ec$k9N<-p?gR=GvvZ4TNaA16so0awVii}H!O@$#l- zHBMQ!0nddUl~o?Ed-;|d1{l=NHZ~js3YT=IBG4#lJy|pj-95fZ?0?wY5Zfs{m96iE z&KaI0x7(2J=RWtm-MD5CezqFB@2CSKg3d*W_W{_?uJh7Dc;VbE0o)}e(sMt{(Hzw3Th*OcW#%xwl51-lS2 zZt8L{B2Y5UJgfds;L=6Y2l5x+2fxgkGacXs}=Ilf_5=png`^*IUUuHUG?$?{XNc z6x^|>og%D3hdCuqHONEg;rcz^9&^K~=ZkYgLVeLZs%hLY{U;ebF4`+e<4huL)}Rp9 z_zo@ECC}ju_rD}J!cyH(AMy5nGHu_+2ASnxzc^&he|N;gXcSJR2G6xEKnfUR`q>tGk!M~z-B>?0 zLPwy?X49LgOF>9Qg}G8KDcJmZKR*Zxk|6Ggp$1_X zd%Hxa(>~OtDvnOfs=kLXDfqH^_#}KusOkECFgP4U50!7dN4x`KQ4lBG;vgm7Ya>9G zXvoZ|HQ%&OaebZNax3kXRh2m5uhMGCQA@n-L#DBRfBJ6mMN4i4W9Hig@%;QfWdA-o zx`TtU%|1TD*9-WWL}|pR$KrK6gQ)}W0fR(ChlQJKY6X68IQce|ghnHDWL{#)>{w=x zIx#1oC3M1CZ;twtWBQ0Kvd^od#_k5O;AzrTdkqr$z2s*iD|({R-Z=6dJ&%>hNY!UN z4DSY(WYAK0&xJXN&U*vMqvtE#X{$`zmTd0a zYkiwg0vHeZrvQ9)3ot+8xH;3EV_zIu()}RO2p(ct<#TdtSN7CFQ$=c7O#4?OTn@{- zBY!UKFOR#|7F7eK2C#!xQZQR|>;%fyq_2#Hh4bUIv6xs)`!{y?OuFM1M)NVVe!T0B ze+!OgiRn|##p_-$o17@-hi5#8y*UTsXVmO2J*8h`LCv|C%KJllN&3(i32`JWPHfz5 zcx3_;;OP;p&(1jc8S1XO>;P3o0Ek`$k>fyldbIe#=h7KT!tP4;a`rIi> zH#4vLZVro6d^*DOoZFv@5Q!1F*P0pR(6mRzw^m=8&r@O}D#lV^MeOYVz zDHmDh2u^j!8Ozjtc>}u`bezSywu9iMoZa*i2msA~h%z|jR>{hW&U?zubv5BAhI7ea z;_GXC;+}{Nd++eVbpXvxMtp*6DeB@NBRD{OTSAMbchd#Z26cPh(~64Lgjyzy%dRH* zRf~SmbT`FEpVMCs8gon0_AdF!w!69u4R6ozG}sb5MDJS7B}bBUz@1hT)z3-*k@R_Z zb-cyjk^f9$=0@?6{4YI7|Bn9u{^Kf9eT5p-$r=`11Xh+v^bUW;>RA2ac8P|CkC%Gm z*U(v(Rm+XLUaX^eGF7XE6~{!z#ijQVU1K>k5ThB}))T9fx`ZiRWyXXCT~kzyGeWD- z8>}}W$5yCXZm*A(NHO-WF0V4vXi(5iyEGi23L5$)jbuEHEcW-ls3JmeUjvapX{fvz zy2O52`+SJ4(3cJz98cP~gV5`~W#I5GjN>s6w4d(qzvM4f-fu1Fw%&Ce3y`&C`dt z##lM=s7w=QWvj`fRussP4<38G9|vLxr1CCmZv_~o7!w%nrc6Oxbm5$Lv$oJ`mK`Rq zu0foXwdYg*Jm(|6!5e6q-9z{^@3Kf70wDQNa$GVvempn19G(=is5y5SlKK*lkNuqy ziM}_2>Uq-0WpA`_@^QSjsmNMs2qO2wrC-4YnwE*30d4~2WC7ajt z?5XGM?_ZhZeYVAXRppu7QbP7Iyb@N8uRC$JKi#u9PB)*O1~1m`uK9uYB>?Sa-!vb5 z2!uYz*C7b5%d+>#F$U4p6>XSZMK09Qqoc_b$^jp}r>RWhCaq(6YtF*T+-hpFUk#{p z0vD!?ZFa8&ddA;ImiY@z>>BNoH5n_q=g&!ecoy>fD)O-rV=fEiih;hMMiN-_dB`Ef zv}a_92c)L9HD%o1tjK%2WY&y^9!~pibIQX?=(Wa~2^gjYvp7zPA_ie;b{E~DxD~TW zf3FpREOAV7^TLya!iULJ2Xmi01gsL($^*xlr(bS}S&Eg=|JH_@J8nd6EyxzLdA#QA zi~THCCU%R4>;6dv6^f^8Z7jx>a@k>f*A$ zB*@oP3J;Tg?aGHWDMwJ$M(kceKq2=5 z(k*2)Afns(enel=YAIJWjbJ?DmMY`s*$Lp|064Jsqu9;yf<6VaKGnvj19M! zNAYl}U3yCrlpAP3B9$SeztKxJutaN4HuD@h^_nQ()>pwOGp>Q|5;e=cWtTQ$h;K2? zu*$7;?Pwn_8-=da-|2h7gpJUtgXIXf#tD~Fjn6)ptf5N5yv(R5QlkwT z%)7FBt#LEc66=ee98E7Qsokp^3$#O>SF|49ScYiS6!Y#YKSWsx;Y%2lKMY+ zH)XU~4Fw6~QH!dh6gEE0~A@ythwLKe78 zGU_8KZ@fPj+-$*(ddb9`qu>d{qTNNj&L5#?FXBlfH-G#1#V{^Pf;#eb-UCxvpZsAQ z;nPx<__9>6Cz#BhiAlfC7r|kZ?#FAmXTcWi6gz+K?I%*QAMg$OgHFtFD(-CKdE2C9 z8{xT-=cdPuq;iAuG6z68jh$Hnrv6|hO=H{ zA8BJKWRD_Y3d_;*d=Z5v5 z1#Eu_(S6W(ag%#BQOn=+oXVec1aSPGx9LV1_xyM-6+~1lG&Kfr*Y?zl34)0wb5}!t z4&J|)@6uaf_GoF_iaB}LS7|>Hxjc4uK70mV-+Q?dS@3N%5P4eGSW!2Hwr!feXaEN3 zFmERwM5qR=hu}S6yvP>pOq0i)00b=DCqU;Y{`xooDb3;sMe0kX!#ZJ%kS2c-S5L28 zyT^)D7ViCmDF^)gackd#$jeQz_sWNWu1HxcABJ{U=ltnzLA^%?s%o@iKjl8(XeZBs zn+=0z?4(d==x#BV@hQ}?aaPAN`3#(uWd_Wiiu*8DfF5Enp3!42L72qQh#28gnv1?U z)U>#<*=KReX8pYHmiR(jsk2?swE+bn1ehe-;-O^aWd(rEi~@7F`wum)n#$VIn)8gA z>ddB&guR1yW?`4+pN;(_7Z@BV{tkf`2e5hJasG$b4iWp{kRnv}?RU2; zJ+2Lh;M8m(f-Kg21)qhD?|_H-whY%|w9Fk97B1H*8}@9}t zo_XE+z-Mq`_XZy&+T0?aX!6M2WL!%pd>CjuESGkBDl4G#abef(vWWvil)cFCM53iI za$exOM1Ri(+x*FO3nCBcj6VMUz|tb&Ban{)pOl5J5u!Y=eXf4^Ki?PPkJ0QB>$Q+sPqHr0Nz9TXq7jzYhJO46-N7N8eTC5Z$9%LT`o7Q}qbTppXGHYrhxWFPo}*0O5~kKV7?eOdf^xZYMM z!Sdw_-(bv@Kd#+=)V`-XD}oN0W|KhsKz`mYjIUdm$&DeS1?ZXSXM{LD9{Ud)1{Qp_ z5nKZhVxD8X+RkOvi%t7RpFKEC8jRA{2Paznrd6kIhLEwI$efnqlW_Yx7x~_%{<4Jg zl9sr%dX3j(4Iq*q-O@CFuxoS??|yZ>8^+e|=>RHfrvtp6z*3 zhRM>6*7#&bAoY=6VVpHcC2|syu&8CPkkr?N*8sc>V(a^+Q=Mkjw0*7L`L@>D@|N_f zV`X3X#~V+#)TECoh)IkrJvGT{2hF?oCTrs(7q>!kH@n;CP5c&dTa1|WePX6mC}_uI z5|}VNYyGmk_p0-@lKfq<3yqBV$f8+WnJfhA!Of_r)+yItSpT6U`#@gnwK^VSH{tg2 zVqWLsLAD6p>#u+GbPXmis3O~@;NfP*yn3ptr zw6X;10JHi(9P`wY?SavH>O_cx=XxcWWWIlsFX40)Ez0uraOqu_<`+k|Jq20BqmdYz zc5p~FLAF%*>pxzDB&~eTwv3?KP)Hz*f;4-quPVIK^>8L6VTGLr!2{Khx5X zRTt5iHGDcWwo!{OMRIb_{vcKew{eozf*pwdf({vm> zIcjMm-8AOQZ6!M!?}Xa!pK=3p37&Se?P$&Mp9dYcqBbeH80Llk7z>fy9XH=}D|`GP zQR&N~N&f>1G3^Px-g}|IbAG(RvC|~liZ})xrGrBoDemY`;E^iX$@DNZUxwH8=v~&!GB4<+^YXe0#1PbX?hGg5blP~ z!ZN4~&Ub0f{SH(oBy^R%ZHoWx?8JE5f6h$M>F8ep1e1_F$ae9}ys1#jQf-8(68F0b zt|X@;s{G*3VmHal17lIYpp`IUI06Ek-R&>QpKf?*A9NKQ3-na{C7F#UmHbQM-|5>n za((~=K40ar|Go?rvfUsWxhpG?LTfm9m`wjZv$#w=Mk zvkIX4{*o+m9TL+v)?s^Nr-3$!(2gJi9RSx}>;MrsD*=CWiT~#l$!!mV1=vIPRu(KY z1i|?JVe-;EgZ79+!M8be$3kOe8_L1oC6<<<-8YCN literal 0 HcmV?d00001 diff --git a/interatomic_potentials/configs/schnet/schnet_md17_ethanol.yaml b/interatomic_potentials/configs/schnet/schnet_md17_ethanol.yaml new file mode 100644 index 00000000..3fa0d418 --- /dev/null +++ b/interatomic_potentials/configs/schnet/schnet_md17_ethanol.yaml @@ -0,0 +1,107 @@ +Global: + do_train: True + do_eval: True + do_test: False + + label_names: ['energy'] + + graph_converter: + __class_name__: FindPointsInSpheres + __init_params__: + cutoff: 5.0 + + prim_eager_enabled: True + + +Trainer: + max_epochs: 500 + seed: 42 + output_dir: ./output/schnet_md17_ethanol + save_freq: 50 + log_freq: 50 + + start_eval_epoch: 1 + eval_freq: 5 + pretrained_model_path: null + pretrained_weight_name: null + resume_from_checkpoint: null + use_amp: False + eval_with_no_grad: True + gradient_accumulation_steps: 1 + + best_metric_indicator: 'eval_metric' + name_for_best_metric: "energy" + greater_is_better: False + + +Model: + __class_name__: SchNet + __init_params__: + n_atom_basis: 64 + n_interactions: 6 + n_filters: 64 + cutoff: 5.0 + n_gaussians: 25 + max_z: 100 + readout: "sum" + property_names: ${Global.label_names} + data_mean: 0.0 + data_std: 1.0 + loss_type: "l1_loss" + compute_forces: False + + +Optimizer: + __class_name__: Adam + __init_params__: + lr: + __class_name__: Cosine + __init_params__: + learning_rate: 1e-4 + eta_min: 1e-7 + by_epoch: False + + +Metric: + energy: + __class_name__: IgnoreNanMetricWrapper + __init_params__: + __class_name__: paddle.nn.L1Loss + __init_params__: {} + + +Dataset: + train: + dataset: + __class_name__: MD17Dataset + __init_params__: + path: "./data/md17" + molecule: "ethanol" + property_names: ${Global.label_names} + build_graph_cfg: ${Global.graph_converter} + max_samples: 50000 + num_workers: 4 + use_shared_memory: False + sampler: + __class_name__: BatchSampler + __init_params__: + shuffle: True + drop_last: False + batch_size: 64 + val: + dataset: + __class_name__: MD17Dataset + __init_params__: + path: "./data/md17" + molecule: "ethanol" + property_names: ${Global.label_names} + build_graph_cfg: ${Global.graph_converter} + max_samples: 10000 + num_workers: 4 + use_shared_memory: False + sampler: + __class_name__: BatchSampler + __init_params__: + shuffle: False + drop_last: False + batch_size: 64 diff --git a/interatomic_potentials/configs/schnet/schnet_qm9_U0.yaml b/interatomic_potentials/configs/schnet/schnet_qm9_U0.yaml new file mode 100644 index 00000000..88b50ad3 --- /dev/null +++ b/interatomic_potentials/configs/schnet/schnet_qm9_U0.yaml @@ -0,0 +1,109 @@ +Global: + do_train: True + do_eval: True + do_test: False + + label_names: ['energy_U0'] + + graph_converter: + __class_name__: FindPointsInSpheres + __init_params__: + cutoff: 10.0 + + prim_eager_enabled: True + + +Trainer: + max_epochs: 200 + seed: 42 + output_dir: ./output/schnet_qm9_U0 + save_freq: 20 + log_freq: 50 + + start_eval_epoch: 1 + eval_freq: 5 + pretrained_model_path: null + pretrained_weight_name: null + resume_from_checkpoint: null + use_amp: False + eval_with_no_grad: True + gradient_accumulation_steps: 1 + + best_metric_indicator: 'eval_metric' + name_for_best_metric: "energy_U0" + greater_is_better: False + + +Model: + __class_name__: SchNet + __init_params__: + n_atom_basis: 128 + n_interactions: 6 + n_filters: 128 + cutoff: 10.0 + n_gaussians: 50 + max_z: 100 + readout: "sum" + property_names: ${Global.label_names} + data_mean: -76.1160 + data_std: 10.3238 + loss_type: "l1_loss" + compute_forces: False + + +Optimizer: + __class_name__: Adam + __init_params__: + lr: + __class_name__: Cosine + __init_params__: + learning_rate: 1e-4 + eta_min: 1e-7 + by_epoch: False + + +Metric: + energy_U0: + __class_name__: IgnoreNanMetricWrapper + __init_params__: + __class_name__: paddle.nn.L1Loss + __init_params__: {} + + +Dataset: + train: + dataset: + __class_name__: QM9Dataset + __init_params__: + path: "./data/qm9" + property_names: ${Global.label_names} + build_graph_cfg: ${Global.graph_converter} + cache_path: "./data/qm9" + overwrite: False + filter_unvalid: True + num_workers: 4 + use_shared_memory: False + sampler: + __class_name__: BatchSampler + __init_params__: + shuffle: True + drop_last: False + batch_size: 64 + val: + dataset: + __class_name__: QM9Dataset + __init_params__: + path: "./data/qm9" + property_names: ${Global.label_names} + build_graph_cfg: ${Global.graph_converter} + cache_path: "./data/qm9" + overwrite: False + filter_unvalid: True + num_workers: 4 + use_shared_memory: False + sampler: + __class_name__: BatchSampler + __init_params__: + shuffle: False + drop_last: False + batch_size: 64 diff --git a/ppmat/datasets/alloy_dataset.py b/ppmat/datasets/alloy_dataset.py new file mode 100644 index 00000000..545e609b --- /dev/null +++ b/ppmat/datasets/alloy_dataset.py @@ -0,0 +1,88 @@ +# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +AlloyDataset — tabular dataset for metallic glass alloy compositions. + +Loads Alloy_train.csv produced by tools/prepare_alloy_data.py. +Each sample is a 66-dimensional float vector: + columns 0-39: element composition fractions (40 elements) + columns 40-42: Tg, Tx, Tl (thermal transition temperatures in K) + columns 43-65: 23 GFA criteria (derived from Tg/Tx/Tl) + +The "source" column is dropped on load (same as original AlloyGAN). +""" + +import numpy as np +import paddle +from paddle.io import Dataset + +from ppmat.utils import logger + + +class AlloyDataset(Dataset): + """Tabular dataset for AlloyGAN training. + + Args: + path: Path to Alloy_train.csv. + categories: Optional list of dominant-element categories to filter + (e.g., ["Cu", "Fe", "Ti", "Zr"]). Default uses all entries. + normalize: Whether to normalize composition fractions to [0, 1]. + Default True (divides compositions by 100). + """ + + # Top 40 elements in order (matches CSV columns 0-39) + ELEMENTS = [ + "Cu", "Zr", "Al", "Ni", "Ti", "Ag", "Fe", "Mg", "B", "Si", + "Nb", "Y", "Ca", "La", "Co", "Be", "C", "Mo", "Pd", "P", + "Sn", "Cr", "Hf", "Zn", "Gd", "Ce", "Er", "Ga", "Au", "Nd", + "Dy", "W", "Pr", "Ta", "Sc", "Li", "Sm", "S", "Pt", "Mn", + ] + + def __init__(self, path, categories=None, normalize=True): + super().__init__() + import pandas as pd + + df = pd.read_csv(path) + + # Drop the "source" column if present (same as original code) + if "source" in df.columns: + df = df.drop(columns=["source"]) + + # Optional category filtering by dominant element + if categories is not None: + elem_cols = df.columns[:40] + dominant = df[elem_cols].idxmax(axis=1) + mask = dominant.isin(categories) + df = df[mask].reset_index(drop=True) + logger.info( + f"Filtered to categories {categories}: " + f"{len(df)} entries" + ) + + self.data = df.values.astype(np.float32) + + if normalize: + # Normalize composition fractions (0-100) to (0-1) + self.data[:, :40] = self.data[:, :40] / 100.0 + + logger.info( + f"Loaded AlloyDataset: {len(self.data)} samples, " + f"{self.data.shape[1]} features from {path}" + ) + + def __len__(self): + return len(self.data) + + def __getitem__(self, idx): + return {"data": self.data[idx]} diff --git a/ppmat/datasets/md17_dataset.py b/ppmat/datasets/md17_dataset.py new file mode 100644 index 00000000..d75a632a --- /dev/null +++ b/ppmat/datasets/md17_dataset.py @@ -0,0 +1,250 @@ +# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""MD17 dataset for molecular dynamics trajectories. + +The MD17 dataset (Chmiela et al., 2017) contains ab-initio molecular dynamics +trajectories for small organic molecules. Each snapshot includes atomic +positions, total energy, and per-atom forces. + +Reference: + S. Chmiela, A. Tkatchenko, H. E. Sauceda, I. Poltavsky, K. T. Schütt, + K.-R. Müller. Machine Learning of Accurate Energy-Conserving Molecular + Force Fields. Science Advances, 2017. +""" + +from __future__ import annotations + +import os +import os.path as osp +import pickle +from typing import Any, Callable, Dict, List, Optional, Union + +import numpy as np +import paddle.distributed as dist +from paddle.io import Dataset + +from ppmat.models import build_graph_converter +from ppmat.utils import download, logger + +try: + from pymatgen.core import Lattice, Structure +except ImportError: + Structure = None + Lattice = None + + +# Mapping from molecule name to original MD17 NPZ filename. +MD17_FILES = { + "benzene": "md17_benzene2017.npz", + "uracil": "md17_uracil.npz", + "naphthalene": "md17_naphthalene.npz", + "aspirin": "md17_aspirin.npz", + "salicylic_acid": "md17_salicylic.npz", + "malonaldehyde": "md17_malonaldehyde.npz", + "ethanol": "md17_ethanol.npz", + "toluene": "md17_toluene.npz", +} + +# Atomic number → element symbol (for pymatgen Structure creation). +_Z_TO_SYMBOL = { + 1: "H", 6: "C", 7: "N", 8: "O", 9: "F", 16: "S", +} + + +class MD17Dataset(Dataset): + """MD17 molecular dynamics trajectory dataset. + + Loads an MD17 NPZ file and converts each snapshot into a dict compatible + with PaddleMaterials models (optionally building a PGL graph via the + graph converter). + + The NPZ files contain: + - ``z``: atomic numbers, shape [num_atoms] + - ``R``: positions, shape [num_snapshots, num_atoms, 3] (Angstrom) + - ``E``: energies, shape [num_snapshots, 1] (kcal/mol) + - ``F``: forces, shape [num_snapshots, num_atoms, 3] (kcal/mol/A) + + Args: + path (str): Root directory for dataset storage. + molecule (str): Molecule name (e.g. "ethanol"). + property_names (str or list): Target property name(s). Default: "energy". + build_graph_cfg (dict, optional): Config for graph converter. + max_samples (int, optional): Limit dataset size (for faster debugging). + url (str, optional): Custom download URL. Default: BCS mirror. + box_size (float): Side length (A) of the cubic cell used for + non-periodic molecules. Default: 100.0. + cache_graphs (bool): Whether to cache built graphs to disk. Default: True. + """ + + # BCS mirror for MD17 NPZ files + default_url = "https://paddle-org.bj.bcebos.com/paddlematerials/datasets/MD17" + + def __init__( + self, + path: str, + molecule: str = "ethanol", + property_names: Union[str, List[str]] = "energy", + *, + build_graph_cfg: Optional[Dict] = None, + max_samples: Optional[int] = None, + url: Optional[str] = None, + box_size: float = 100.0, + cache_graphs: bool = True, + **kwargs, + ) -> None: + super().__init__() + + if molecule not in MD17_FILES: + raise ValueError( + f"Unknown molecule '{molecule}'. Choose from: {list(MD17_FILES)}" + ) + + if isinstance(property_names, str): + property_names = [property_names] + self.property_names = property_names + self.molecule = molecule + self.box_size = box_size + self.build_graph_cfg = build_graph_cfg + + # Paths + os.makedirs(path, exist_ok=True) + self.raw_dir = osp.join(path, "raw_md17") + os.makedirs(self.raw_dir, exist_ok=True) + + npz_name = MD17_FILES[molecule] + npz_path = osp.join(self.raw_dir, npz_name) + + # Download if needed + if not osp.exists(npz_path): + base_url = url or self.default_url + full_url = f"{base_url}/{npz_name}" + logger.info(f"Downloading MD17 {molecule} from {full_url}") + download.download_file(full_url, npz_path) + + # Load raw data + raw = np.load(npz_path) + self.atomic_numbers = raw["z"].astype(np.int64) # [num_atoms] + self.positions = raw["R"].astype(np.float32) # [N, num_atoms, 3] + self.energies = raw["E"].astype(np.float32) # [N, 1] or [N] + self.forces = raw["F"].astype(np.float32) # [N, num_atoms, 3] + + if self.energies.ndim == 1: + self.energies = self.energies[:, None] + + if max_samples is not None: + self.positions = self.positions[:max_samples] + self.energies = self.energies[:max_samples] + self.forces = self.forces[:max_samples] + + self.num_samples = len(self.positions) + logger.info( + f"MD17 {molecule}: {self.num_samples} snapshots, " + f"{len(self.atomic_numbers)} atoms/snapshot" + ) + + # Build and cache graphs if configured + self.graphs = None + if build_graph_cfg is not None: + graph_converter_name = build_graph_cfg.get("__class_name__", "custom") + cutoff = build_graph_cfg.get("__init_params__", {}).get("cutoff", 5) + cache_dir = osp.join( + path, + f"md17_{molecule}_cache_{graph_converter_name}_cutoff_{int(cutoff)}", + "graphs", + ) + + done_flag = osp.join(cache_dir, "completed.flag") + if cache_graphs and osp.exists(done_flag): + logger.info(f"Loading cached graphs from {cache_dir}") + self.graphs = self._load_cached_graphs(cache_dir) + else: + if dist.get_rank() == 0: + logger.info("Building graphs for MD17 dataset...") + os.makedirs(cache_dir, exist_ok=True) + converter = build_graph_converter(build_graph_cfg) + structures = self._build_structures() + self.graphs = converter(structures) + if cache_graphs: + self._save_cached_graphs(cache_dir) + with open(done_flag, "w") as f: + f.write("done") + if dist.is_initialized(): + dist.barrier() + if self.graphs is None: + self.graphs = self._load_cached_graphs(cache_dir) + + def _build_structures(self) -> list: + """Convert all snapshots to pymatgen Structures.""" + if Structure is None: + raise RuntimeError("pymatgen is required: pip install pymatgen") + + lattice = Lattice.from_parameters( + self.box_size, self.box_size, self.box_size, 90, 90, 90 + ) + species = [_Z_TO_SYMBOL.get(z, str(z)) for z in self.atomic_numbers] + + structures = [] + for i in range(self.num_samples): + coords = self.positions[i] # [num_atoms, 3] + struct = Structure( + lattice, + species, + coords, + coords_are_cartesian=True, + ) + structures.append(struct) + return structures + + def _save_cached_graphs(self, cache_dir: str) -> None: + for i, g in enumerate(self.graphs): + with open(osp.join(cache_dir, f"{i:08d}.pkl"), "wb") as f: + pickle.dump(g, f) + + def _load_cached_graphs(self, cache_dir: str) -> list: + files = sorted( + f for f in os.listdir(cache_dir) if f.endswith(".pkl") + ) + graphs = [] + for fn in files: + with open(osp.join(cache_dir, fn), "rb") as f: + graphs.append(pickle.load(f)) + return graphs + + def __len__(self) -> int: + return self.num_samples + + def __getitem__(self, idx: int) -> Dict[str, Any]: + data = {} + + if self.graphs is not None: + data["graph"] = self.graphs[idx] + else: + # Return raw data without graph (fallback) + data["pos"] = self.positions[idx] + data["atomic_numbers"] = self.atomic_numbers.copy() + data["cell"] = np.eye(3, dtype="float32") * self.box_size + data["natoms"] = len(self.atomic_numbers) + data["pbc"] = np.array([False, False, False], dtype=bool) + + # Properties + for pname in self.property_names: + if pname == "energy": + data["energy"] = self.energies[idx] + elif pname == "forces": + data["forces"] = self.forces[idx] + else: + data[pname] = self.energies[idx] + + return data diff --git a/ppmat/models/__init__.py b/ppmat/models/__init__.py index 95d73232..8e674bc6 100644 --- a/ppmat/models/__init__.py +++ b/ppmat/models/__init__.py @@ -42,6 +42,7 @@ from ppmat.models.megnet.megnet import MEGNetPlus from ppmat.models.infgcn.infgcn import InfGCN from ppmat.models.mateno.mateno import MatENO +from ppmat.models.wd_mpnn.wd_mpnn import WDMPNN from ppmat.utils import download from ppmat.utils import logger from ppmat.utils import save_load @@ -67,6 +68,7 @@ "DiffNMR", "InfGCN", "MatENO", + "WDMPNN", ] # Warning: The key of the dictionary must be consistent with the file name of the value diff --git a/ppmat/models/wd_mpnn/__init__.py b/ppmat/models/wd_mpnn/__init__.py new file mode 100644 index 00000000..fc39458f --- /dev/null +++ b/ppmat/models/wd_mpnn/__init__.py @@ -0,0 +1,3 @@ +from ppmat.models.wd_mpnn.wd_mpnn import WDMPNN + +__all__ = ["WDMPNN"] diff --git a/ppmat/models/wd_mpnn/featurization.py b/ppmat/models/wd_mpnn/featurization.py new file mode 100644 index 00000000..6d0dad2b --- /dev/null +++ b/ppmat/models/wd_mpnn/featurization.py @@ -0,0 +1,169 @@ +""" +Simplified molecular featurization for wD-MPNN. + +Provides MolGraph and BatchMolGraph classes for building molecular graph +representations suitable for message passing neural networks. Designed to +work without RDKit dependency by accepting pre-computed features. + +Ported from: https://github.com/Ramprasad-Group/polymer-chemprop +""" + +from typing import List, Optional, Tuple + +import numpy as np +import paddle + +ATOM_FDIM = 133 +BOND_FDIM = 14 + + +def index_select_ND(source: paddle.Tensor, index: paddle.Tensor) -> paddle.Tensor: + """ + Select entries from source along dim=0 using a 2-D index tensor. + + Args: + source: Tensor of shape (N, hidden_size). + index: Tensor of shape (M, max_neighbors) with integer indices into source. + + Returns: + Tensor of shape (M, max_neighbors, hidden_size). + """ + index_shape = index.shape # (M, max_neighbors) + suffix_dim = source.shape[1:] # (hidden_size,) or similar + final_shape = list(index_shape) + list(suffix_dim) + + flat_index = index.reshape([-1]) # (M * max_neighbors,) + target = paddle.index_select(source, flat_index, axis=0) + target = target.reshape(final_shape) + return target + + +class MolGraph: + """ + Molecular graph representation for a single molecule. + + Stores atom features, bond features, adjacency structures, and + optional weight vectors for polymer-aware message passing. + """ + + def __init__( + self, + f_atoms: np.ndarray, + f_bonds: np.ndarray, + a2b: List[List[int]], + b2a: np.ndarray, + b2revb: np.ndarray, + w_atoms: Optional[np.ndarray] = None, + w_bonds: Optional[np.ndarray] = None, + degree_of_polym: float = 1.0, + ): + """ + Args: + f_atoms: Atom feature matrix of shape (n_atoms, atom_fdim). + f_bonds: Bond feature matrix of shape (n_bonds, bond_fdim). + a2b: List of lists mapping each atom to its incident bond indices. + b2a: Array mapping each bond to its source atom. + b2revb: Array mapping each bond to its reverse bond. + w_atoms: Per-atom weights (default: all ones). + w_bonds: Per-bond weights (default: all ones). + degree_of_polym: Degree of polymerization multiplier. + """ + self.n_atoms = f_atoms.shape[0] + self.n_bonds = f_bonds.shape[0] + self.f_atoms = f_atoms + self.f_bonds = f_bonds + self.a2b = a2b + self.b2a = b2a + self.b2revb = b2revb + self.w_atoms = w_atoms if w_atoms is not None else np.ones(self.n_atoms, dtype=np.float32) + self.w_bonds = w_bonds if w_bonds is not None else np.ones(self.n_bonds, dtype=np.float32) + self.degree_of_polym = degree_of_polym + + +class BatchMolGraph: + """ + Batched molecular graph that merges multiple MolGraph instances. + + Handles padding of adjacency lists and offset shifting so that the + message passing encoder can process an entire batch in one forward call. + """ + + def __init__(self, mol_graphs: List[MolGraph]): + self.atom_fdim = mol_graphs[0].f_atoms.shape[1] + self.bond_fdim = mol_graphs[0].f_bonds.shape[1] + self.n_mols = len(mol_graphs) + + # Running offsets + n_atoms = 1 # leave index 0 as padding atom + n_bonds = 1 # leave index 0 as padding bond + + f_atoms = [np.zeros((1, self.atom_fdim), dtype=np.float32)] # padding row + f_bonds = [np.zeros((1, self.bond_fdim), dtype=np.float32)] # padding row + w_atoms = [np.zeros(1, dtype=np.float32)] # padding + w_bonds = [np.zeros(1, dtype=np.float32)] # padding + a2b_all: List[List[int]] = [[]] # padding atom's neighbor list + b2a = [0] + b2revb = [0] + a_scope = [] + b_scope = [] + degree_of_polym = [] + + for mg in mol_graphs: + a_scope.append((n_atoms, mg.n_atoms)) + b_scope.append((n_bonds, mg.n_bonds)) + + f_atoms.append(mg.f_atoms) + f_bonds.append(mg.f_bonds) + w_atoms.append(mg.w_atoms) + w_bonds.append(mg.w_bonds) + + for atom_a2b in mg.a2b: + a2b_all.append([b + n_bonds for b in atom_a2b]) + + b2a.extend(mg.b2a + n_atoms) + b2revb.extend(mg.b2revb + n_bonds) + + degree_of_polym.append(mg.degree_of_polym) + + n_atoms += mg.n_atoms + n_bonds += mg.n_bonds + + self.f_atoms = paddle.to_tensor(np.concatenate(f_atoms, axis=0), dtype="float32") + self.f_bonds = paddle.to_tensor(np.concatenate(f_bonds, axis=0), dtype="float32") + self.w_atoms = paddle.to_tensor(np.concatenate(w_atoms, axis=0), dtype="float32") + self.w_bonds = paddle.to_tensor(np.concatenate(w_bonds, axis=0), dtype="float32") + self.b2a = paddle.to_tensor(np.array(b2a, dtype=np.int64)) + self.b2revb = paddle.to_tensor(np.array(b2revb, dtype=np.int64)) + self.a_scope = a_scope + self.b_scope = b_scope + self.degree_of_polym = degree_of_polym + + # Pad a2b to rectangular tensor + max_num_bonds = max(len(bonds) for bonds in a2b_all) if a2b_all else 1 + max_num_bonds = max(max_num_bonds, 1) + a2b_padded = np.zeros((n_atoms, max_num_bonds), dtype=np.int64) + for i, bonds in enumerate(a2b_all): + for j, b in enumerate(bonds): + a2b_padded[i, j] = b + self.a2b = paddle.to_tensor(a2b_padded) + + def get_components(self): + """ + Return all graph components needed by MPNEncoder. + + Returns: + Tuple of (f_atoms, f_bonds, w_atoms, w_bonds, a2b, b2a, b2revb, + a_scope, b_scope, degree_of_polym). + """ + return ( + self.f_atoms, + self.f_bonds, + self.w_atoms, + self.w_bonds, + self.a2b, + self.b2a, + self.b2revb, + self.a_scope, + self.b_scope, + self.degree_of_polym, + ) diff --git a/ppmat/models/wd_mpnn/wd_mpnn.py b/ppmat/models/wd_mpnn/wd_mpnn.py new file mode 100644 index 00000000..99c0bb93 --- /dev/null +++ b/ppmat/models/wd_mpnn/wd_mpnn.py @@ -0,0 +1,366 @@ +""" +Weighted Directed Message Passing Neural Network (wD-MPNN) for PaddleMaterials. + +Ported from: https://github.com/Ramprasad-Group/polymer-chemprop + +The model performs directed message passing on molecular graphs with optional +per-atom and per-bond weights (for polymer-aware predictions), followed by a +feed-forward network to produce property predictions. + +Architecture: + 1. MPNEncoder – directed message passing with weighted edges + 2. FFN – feed-forward network for final prediction +""" + +from typing import Dict, List, Optional, Tuple, Union +import math + +import numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as F + +from ppmat.models.wd_mpnn.featurization import BatchMolGraph, MolGraph, index_select_ND + + +class MPNEncoder(nn.Layer): + """ + Directed message passing encoder for molecular graphs. + + Implements the wD-MPNN message passing formula: + m(a1→a2) = Σ_{a0∈nei(a1)} m(a0→a1) * w(a0→a1) − m(a2→a1) + + followed by atom-level readout with weighted aggregation. + """ + + def __init__( + self, + atom_fdim: int, + bond_fdim: int, + hidden_size: int = 300, + depth: int = 3, + dropout: float = 0.0, + aggregation: str = "mean", + aggregation_norm: float = 100.0, + bias: bool = True, + ): + super().__init__() + self.atom_fdim = atom_fdim + self.bond_fdim = bond_fdim + self.hidden_size = hidden_size + self.depth = depth + self.aggregation = aggregation + self.aggregation_norm = aggregation_norm + + self.dropout_layer = nn.Dropout(p=dropout) + self.act_func = nn.ReLU() + + # Cached zero vector for empty molecules + self.register_buffer( + name="cached_zero_vector", + tensor=paddle.zeros([hidden_size]), + ) + + # Input projection: bond features → hidden + self.W_i = nn.Linear(bond_fdim, hidden_size, bias_attr=bias) + # Message update + self.W_h = nn.Linear(hidden_size, hidden_size, bias_attr=bias) + # Output projection: (atom features || hidden) → hidden + self.W_o = nn.Linear(atom_fdim + hidden_size, hidden_size, bias_attr=True) + + def forward( + self, + f_atoms: paddle.Tensor, + f_bonds: paddle.Tensor, + w_atoms: paddle.Tensor, + w_bonds: paddle.Tensor, + a2b: paddle.Tensor, + b2a: paddle.Tensor, + b2revb: paddle.Tensor, + a_scope: List[Tuple[int, int]], + degree_of_polym: List[float], + ) -> paddle.Tensor: + """ + Encode a batched molecular graph. + + Args: + f_atoms: (total_atoms, atom_fdim) atom feature matrix. + f_bonds: (total_bonds, bond_fdim) bond feature matrix. + w_atoms: (total_atoms,) per-atom weights. + w_bonds: (total_bonds,) per-bond weights. + a2b: (total_atoms, max_num_bonds) atom-to-bond adjacency. + b2a: (total_bonds,) bond-to-source-atom mapping. + b2revb: (total_bonds,) bond-to-reverse-bond mapping. + a_scope: List of (start, size) tuples per molecule. + degree_of_polym: Per-molecule degree of polymerization. + + Returns: + Tensor of shape (num_molecules, hidden_size). + """ + # Initial bond message + inp = self.W_i(f_bonds) # (n_bonds, hidden) + message = self.act_func(inp) # (n_bonds, hidden) + + # Message passing iterations + for _ in range(self.depth - 1): + # Gather neighbor messages per atom, weighted by bond weights + nei_a_message = index_select_ND(message, a2b) # (n_atoms, max_bonds, hidden) + nei_a_weight = index_select_ND(w_bonds, a2b) # (n_atoms, max_bonds) + nei_a_message = nei_a_message * nei_a_weight.unsqueeze(-1) + a_message = nei_a_message.sum(axis=1) # (n_atoms, hidden) + + # Subtract reverse message + rev_message = paddle.index_select(message, b2revb, axis=0) # (n_bonds, hidden) + message = paddle.index_select(a_message, b2a, axis=0) - rev_message + + message = self.W_h(message) + message = self.act_func(inp + message) # residual + message = self.dropout_layer(message) + + # Final aggregation: atom hidden states + nei_a_message = index_select_ND(message, a2b) + nei_a_weight = index_select_ND(w_bonds, a2b) + nei_a_message = nei_a_message * nei_a_weight.unsqueeze(-1) + a_message = nei_a_message.sum(axis=1) # (n_atoms, hidden) + + a_input = paddle.concat([f_atoms, a_message], axis=1) + atom_hiddens = self.act_func(self.W_o(a_input)) + atom_hiddens = self.dropout_layer(atom_hiddens) + + # Per-molecule readout + mol_vecs = [] + for i, (a_start, a_size) in enumerate(a_scope): + if a_size == 0: + mol_vecs.append(self.cached_zero_vector) + else: + cur_hiddens = paddle.slice( + atom_hiddens, axes=[0], starts=[a_start], ends=[a_start + a_size] + ) + w_atom_vec = paddle.slice( + w_atoms, axes=[0], starts=[a_start], ends=[a_start + a_size] + ) + # Weight atom representations + mol_vec = w_atom_vec.unsqueeze(-1) * cur_hiddens + + if self.aggregation == "mean": + mol_vec = mol_vec.sum(axis=0) / w_atom_vec.sum(axis=0) + elif self.aggregation == "sum": + mol_vec = mol_vec.sum(axis=0) + elif self.aggregation == "norm": + mol_vec = mol_vec.sum(axis=0) / self.aggregation_norm + + # Scale by degree of polymerization (log-scaled per RFC) + xn = degree_of_polym[i] + mol_vec = (1.0 + math.log(max(xn, 1.0))) * mol_vec + mol_vecs.append(mol_vec) + + mol_vecs = paddle.stack(mol_vecs, axis=0) # (n_mols, hidden) + return mol_vecs + + +class WDMPNN(nn.Layer): + """ + Weighted Directed Message Passing Neural Network. + + Combines an MPNEncoder for molecular graph encoding with a feed-forward + network for property prediction. Follows PaddleMaterials model conventions: + ``forward()`` returns ``{"loss_dict": {...}, "pred_dict": {...}}``. + """ + + def __init__( + self, + hidden_size: int = 300, + depth: int = 3, + dropout: float = 0.0, + ffn_hidden_size: int = 300, + ffn_num_layers: int = 2, + aggregation: str = "mean", + aggregation_norm: float = 100.0, + property_names: Union[str, List[str]] = "property", + data_mean: float = 0.0, + data_std: float = 1.0, + loss_type: str = "mse_loss", + atom_fdim: int = 133, + bond_fdim: int = 14, + bias: bool = True, + output_size: int = 1, + ): + """ + Args: + hidden_size: Hidden dimension for message passing. + depth: Number of message passing iterations. + dropout: Dropout probability. + ffn_hidden_size: Hidden dimension for FFN layers. + ffn_num_layers: Number of FFN layers (including output layer). + aggregation: Readout aggregation type ('mean', 'sum', 'norm'). + aggregation_norm: Normalization constant for 'norm' aggregation. + property_names: Name(s) of the target property. + data_mean: Mean for output normalization. + data_std: Std for output normalization. + loss_type: Loss function ('mse_loss' or 'l1_loss'). + atom_fdim: Atom feature dimension. + bond_fdim: Bond feature dimension. + bias: Whether to use bias in linear layers. + output_size: Number of output targets. + """ + super().__init__() + + if isinstance(property_names, list): + self.property_names = property_names[0] + else: + self.property_names = property_names + + self.hidden_size = hidden_size + self.output_size = output_size + + # Normalization buffers + self.register_buffer( + name="data_mean", tensor=paddle.to_tensor(data_mean, dtype="float32") + ) + self.register_buffer( + name="data_std", tensor=paddle.to_tensor(data_std, dtype="float32") + ) + + # Loss function + if loss_type == "mse_loss": + self.loss_fn = F.mse_loss + elif loss_type == "l1_loss": + self.loss_fn = F.l1_loss + else: + raise ValueError(f"Unsupported loss type: {loss_type}") + + # Encoder + self.encoder = MPNEncoder( + atom_fdim=atom_fdim, + bond_fdim=bond_fdim, + hidden_size=hidden_size, + depth=depth, + dropout=dropout, + aggregation=aggregation, + aggregation_norm=aggregation_norm, + bias=bias, + ) + + # Feed-forward network + self.ffn = self._build_ffn( + first_linear_dim=hidden_size, + ffn_hidden_size=ffn_hidden_size, + ffn_num_layers=ffn_num_layers, + output_size=output_size, + dropout=dropout, + ) + + @staticmethod + def _build_ffn( + first_linear_dim: int, + ffn_hidden_size: int, + ffn_num_layers: int, + output_size: int, + dropout: float, + ) -> nn.Sequential: + """Build the feed-forward network.""" + dropout_layer = nn.Dropout(p=dropout) + activation = nn.ReLU() + + if ffn_num_layers == 1: + layers = [dropout_layer, nn.Linear(first_linear_dim, output_size)] + else: + layers = [dropout_layer, nn.Linear(first_linear_dim, ffn_hidden_size)] + for _ in range(ffn_num_layers - 2): + layers.extend([activation, dropout_layer, nn.Linear(ffn_hidden_size, ffn_hidden_size)]) + layers.extend([activation, dropout_layer, nn.Linear(ffn_hidden_size, output_size)]) + + return nn.Sequential(*layers) + + def normalize(self, tensor: paddle.Tensor) -> paddle.Tensor: + return (tensor - self.data_mean) / self.data_std + + def unnormalize(self, tensor: paddle.Tensor) -> paddle.Tensor: + return tensor * self.data_std + self.data_mean + + def _forward(self, data: Dict) -> paddle.Tensor: + """ + Core forward computation. + + Args: + data: Dict containing either a ``BatchMolGraph`` under key ``"mol_graph"`` + or pre-computed graph components (``f_atoms``, ``f_bonds``, etc.). + + Returns: + Raw predictions of shape (batch_size, output_size). + """ + if "mol_graph" in data: + mol_graph: BatchMolGraph = data["mol_graph"] + ( + f_atoms, f_bonds, w_atoms, w_bonds, + a2b, b2a, b2revb, + a_scope, _b_scope, degree_of_polym, + ) = mol_graph.get_components() + else: + f_atoms = data["f_atoms"] + f_bonds = data["f_bonds"] + w_atoms = data["w_atoms"] + w_bonds = data["w_bonds"] + a2b = data["a2b"] + b2a = data["b2a"] + b2revb = data["b2revb"] + a_scope = data["a_scope"] + degree_of_polym = data.get("degree_of_polym", [1.0] * len(a_scope)) + + encoding = self.encoder( + f_atoms, f_bonds, w_atoms, w_bonds, + a2b, b2a, b2revb, a_scope, degree_of_polym, + ) + output = self.ffn(encoding) + return output + + def forward( + self, + data: Dict, + return_loss: bool = True, + return_prediction: bool = True, + ) -> Dict: + """ + Full forward pass with optional loss and prediction. + + Args: + data: Input data dict with graph components and optionally labels. + return_loss: Whether to compute and return the loss. + return_prediction: Whether to return unnormalized predictions. + + Returns: + Dict with ``"loss_dict"`` and ``"pred_dict"`` entries. + """ + assert return_loss or return_prediction, ( + "At least one of return_loss or return_prediction must be True." + ) + pred = self._forward(data) + + loss_dict = {} + if return_loss: + label = data[self.property_names] + label = self.normalize(label) + loss = self.loss_fn(input=pred, label=label) + loss_dict["loss"] = loss + + prediction = {} + if return_prediction: + pred = self.unnormalize(pred) + prediction[self.property_names] = pred + + return {"loss_dict": loss_dict, "pred_dict": prediction} + + @paddle.no_grad() + def predict(self, data: Dict) -> Dict: + """ + Run inference and return unnormalized predictions. + + Args: + data: Input data dict with graph components. + + Returns: + Dict mapping property name to predicted value. + """ + pred = self._forward(data) + pred = self.unnormalize(pred) + return {self.property_names: pred} diff --git a/property_prediction/configs/wd_mpnn/README.md b/property_prediction/configs/wd_mpnn/README.md new file mode 100644 index 00000000..b06aeee8 --- /dev/null +++ b/property_prediction/configs/wd_mpnn/README.md @@ -0,0 +1,49 @@ +# wD-MPNN + +[A graph representation of molecular ensembles for polymer property prediction](https://doi.org/10.1039/D2SC02839E) + +## Abstract + +Weighted Directed Message Passing Neural Network (wD-MPNN) is a graph neural network that operates on molecular graphs where atoms are nodes and bonds are edges. It uses directed message passing along bonds to learn molecular representations and predict scalar molecular properties. The architecture consists of an MPNEncoder for graph-level embedding followed by a feed-forward network for regression. + +## Model + +wD-MPNN encodes molecules by passing directed messages along bonds in a molecular graph. Each message-passing step aggregates neighbor information weighted by learned edge features, producing an atom-level representation that is then pooled (mean/sum/norm) into a fixed-size molecular fingerprint. A multi-layer FFN maps this fingerprint to the target property. + +## Training + +```bash +# single-gpu training +python property_prediction/train.py -c property_prediction/configs/wd_mpnn/wd_mpnn_qm9_homo.yaml + +# multi-gpu training +python -m paddle.distributed.launch --gpus="0,1,2,3" property_prediction/train.py -c property_prediction/configs/wd_mpnn/wd_mpnn_qm9_homo.yaml +``` + +## Validation + +```bash +python property_prediction/train.py -c property_prediction/configs/wd_mpnn/wd_mpnn_qm9_homo.yaml Global.do_eval=True Global.do_train=False Global.do_test=False Trainer.pretrained_model_path='your model path(*.pdparams)' +``` + +## Testing + +```bash +python property_prediction/train.py -c property_prediction/configs/wd_mpnn/wd_mpnn_qm9_homo.yaml Global.do_test=True Global.do_train=False Global.do_eval=False Trainer.pretrained_model_path='your model path(*.pdparams)' +``` + +## Citation + +``` +@article{aldeghi2022graph, + title={A graph representation of molecular ensembles for polymer property prediction}, + author={Aldeghi, Matteo and Coley, Connor W.}, + journal={Chemical Science}, + volume={13}, + number={35}, + pages={10486--10498}, + year={2022}, + publisher={Royal Society of Chemistry}, + doi={10.1039/D2SC02839E} +} +``` diff --git a/property_prediction/configs/wd_mpnn/wd_mpnn_qm9_homo.yaml b/property_prediction/configs/wd_mpnn/wd_mpnn_qm9_homo.yaml new file mode 100644 index 00000000..dd612d5a --- /dev/null +++ b/property_prediction/configs/wd_mpnn/wd_mpnn_qm9_homo.yaml @@ -0,0 +1,91 @@ +Global: + label_names: ["homo"] + do_train: True + do_eval: False + do_test: False + +Dataset: + dataset: + __class_name__: QM9Dataset + __init_params__: + path: "./data/qm9" + property_names: ${Global.label_names} + num_workers: 4 + use_shared_memory: False + split_dataset_ratio: + train: 0.8 + val: 0.1 + test: 0.1 + train_sampler: + __class_name__: BatchSampler + __init_params__: + shuffle: True + drop_last: False + batch_size: 64 + val_sampler: + __class_name__: BatchSampler + __init_params__: + shuffle: False + drop_last: False + batch_size: 64 + test_sampler: + __class_name__: BatchSampler + __init_params__: + shuffle: False + drop_last: False + batch_size: 64 + +Model: + __class_name__: WDMPNN + __init_params__: + hidden_size: 300 + depth: 3 + dropout: 0.0 + ffn_hidden_size: 300 + ffn_num_layers: 2 + aggregation: mean + aggregation_norm: 100.0 + atom_fdim: 133 + bond_fdim: 14 + bias: True + output_size: 1 + loss_type: mse_loss + property_names: ${Global.label_names} + +Trainer: + max_epochs: 100 + seed: 42 + output_dir: ./output/wd_mpnn_qm9_homo + save_freq: 20 + log_freq: 10 + start_eval_epoch: 1 + eval_freq: 1 + pretrained_model_path: null + pretrained_weight_name: null + resume_from_checkpoint: null + use_amp: False + amp_level: 'O1' + eval_with_no_grad: True + gradient_accumulation_steps: 1 + best_metric_indicator: 'eval_metric' + name_for_best_metric: "homo" + greater_is_better: False + compute_metric_during_train: True + metric_strategy_during_eval: 'epoch' + use_visualdl: False + use_wandb: False + use_tensorboard: False + +Optimizer: + __class_name__: Adam + __init_params__: + lr: + __class_name__: OneCycleLR + __init_params__: + max_learning_rate: 0.001 + by_epoch: True + +Metric: + homo: + __class_name__: paddle.nn.L1Loss + __init_params__: {} diff --git a/test/wd_mpnn/__init__.py b/test/wd_mpnn/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/wd_mpnn/conftest.py b/test/wd_mpnn/conftest.py new file mode 100644 index 00000000..434b919c --- /dev/null +++ b/test/wd_mpnn/conftest.py @@ -0,0 +1,23 @@ +# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Conftest for wD-MPNN tests — stubs heavy dependencies for CPU testing.""" + +import sys +import types + +# Stub pgl (PaddlePaddle Graph Learning) — not needed for unit tests +pgl_stub = types.ModuleType("pgl") +pgl_stub.Graph = type("Graph", (), {}) +sys.modules.setdefault("pgl", pgl_stub) diff --git a/test/wd_mpnn/raw_infer_data/__init__.py b/test/wd_mpnn/raw_infer_data/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/wd_mpnn/raw_infer_data/create_input_output_npz.py b/test/wd_mpnn/raw_infer_data/create_input_output_npz.py new file mode 100644 index 00000000..a74a626e --- /dev/null +++ b/test/wd_mpnn/raw_infer_data/create_input_output_npz.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python +"""Generate reference I/O arrays for wD-MPNN regression testing. + +Equivalent PyTorch code (for cross-framework comparison): + import torch, numpy as np + torch.manual_seed(42); np.random.seed(42) + # Build identical wD-MPNN with PyTorch chemprop-style architecture, + # create same MolGraph inputs, run forward pass, save outputs. + # np.savez("reference_io.npz", pred=pred, loss=loss) + +This script uses the Paddle implementation to create a deterministic +reference snapshot. Re-run only when the model architecture intentionally +changes. +""" + +import importlib.util +import os +import sys + +import numpy as np +import paddle + +_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir)) + +_feat_spec = importlib.util.spec_from_file_location( + "ppmat.models.wd_mpnn.featurization", + os.path.join(_ROOT, "ppmat", "models", "wd_mpnn", "featurization.py"), +) +_feat_mod = importlib.util.module_from_spec(_feat_spec) +sys.modules["ppmat.models.wd_mpnn.featurization"] = _feat_mod +_feat_spec.loader.exec_module(_feat_mod) + +_model_spec = importlib.util.spec_from_file_location( + "ppmat.models.wd_mpnn.wd_mpnn", + os.path.join(_ROOT, "ppmat", "models", "wd_mpnn", "wd_mpnn.py"), +) +_model_mod = importlib.util.module_from_spec(_model_spec) +sys.modules["ppmat.models.wd_mpnn.wd_mpnn"] = _model_mod +_model_spec.loader.exec_module(_model_mod) + +WDMPNN = _model_mod.WDMPNN +BatchMolGraph = _feat_mod.BatchMolGraph +MolGraph = _feat_mod.MolGraph + + +def _create_dummy_mol_graph(n_atoms=5, seed=42): + rng = np.random.RandomState(seed) + n_edges = n_atoms - 1 + n_bonds = 2 * n_edges + f_atoms = rng.randn(n_atoms, 133).astype("float32") + f_bonds = rng.randn(n_bonds, 14).astype("float32") + w_atoms = np.ones(n_atoms, dtype="float32") + w_bonds = np.ones(n_bonds, dtype="float32") + b2a_list, b2revb_list = [], [] + a2b = [[] for _ in range(n_atoms)] + for e in range(n_edges): + fwd, rev = 2 * e, 2 * e + 1 + b2a_list.extend([e, e + 1]) + b2revb_list.extend([rev, fwd]) + a2b[e].append(fwd) + a2b[e + 1].append(rev) + b2a = np.array(b2a_list, dtype="int64") + b2revb = np.array(b2revb_list, dtype="int64") + return MolGraph( + f_atoms=f_atoms, f_bonds=f_bonds, a2b=a2b, + b2a=b2a, b2revb=b2revb, w_atoms=w_atoms, + w_bonds=w_bonds, degree_of_polym=1.0, + ) + + +def main(): + paddle.seed(42) + np.random.seed(42) + model = WDMPNN( + hidden_size=64, depth=3, dropout=0.0, + ffn_hidden_size=64, ffn_num_layers=2, + atom_fdim=133, bond_fdim=14, + property_names="property", + data_mean=0.0, data_std=1.0, loss_type="mse_loss", + ) + model.eval() + + graphs = [_create_dummy_mol_graph(seed=42)] + batch = BatchMolGraph(graphs) + components = batch.get_components() + f_atoms, f_bonds, w_atoms, w_bonds, a2b, b2a, b2revb, a_scope, _b_scope, degree_of_polym = components + data = { + "f_atoms": f_atoms, "f_bonds": f_bonds, + "w_atoms": w_atoms, "w_bonds": w_bonds, + "a2b": a2b, "b2a": b2a, "b2revb": b2revb, + "a_scope": a_scope, "degree_of_polym": degree_of_polym, + "property": paddle.to_tensor([[1.0]], dtype="float32"), + } + + result = model(data, return_loss=True, return_prediction=True) + pred = result["pred_dict"]["property"].numpy() + loss = result["loss_dict"]["loss"].numpy() + + out_path = os.path.join(os.path.dirname(__file__), "reference_io.npz") + np.savez(out_path, pred=pred, loss=loss) + print(f"Saved reference to {out_path}") + print(f" pred shape={pred.shape}, values={pred}") + print(f" loss={loss}") + + +if __name__ == "__main__": + main() diff --git a/test/wd_mpnn/raw_infer_data/reference_io.npz b/test/wd_mpnn/raw_infer_data/reference_io.npz new file mode 100644 index 0000000000000000000000000000000000000000..0266d40aca10cf7b64924c8a707eccee9425c992 GIT binary patch literal 510 zcmWIWW@gc4fB;2?{nct~{zCx=g9t-GQEG}_UO^=zg8)MdR27V#>=)`A5Xs0;#!#)E zl3JWxq;934Zj)xBuA`uymS0p-l$aNvUzCyx5_e0?DNY577iT0EqyqUGhB^v{nmP)# z3S