ravimohan19 commited on
Commit
7189af3
·
verified ·
1 Parent(s): aa6ad0d

Upload examples/polymer_optimization.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. examples/polymer_optimization.py +166 -0
examples/polymer_optimization.py ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Example: Physics-Informed Bayesian Optimization for Polymer Design
3
+
4
+ This example demonstrates optimizing a polymer formulation where:
5
+ - A physics model (simplified Flory-Huggins + Arrhenius kinetics) provides
6
+ prior knowledge about how composition and temperature affect properties.
7
+ - Initial experimental data provides a warm start.
8
+ - The BO loop efficiently explores the design space, leveraging both
9
+ physics and data to minimize the number of experiments needed.
10
+
11
+ Objective: Maximize polymer recyclability metric (higher is better).
12
+ Parameters:
13
+ - monomer_ratio: Ratio of monomer A to B (0.1 to 0.9)
14
+ - temperature: Reaction temperature in Kelvin (350 to 500)
15
+ - catalyst_loading: Catalyst weight percent (0.5 to 5.0)
16
+ """
17
+
18
+ import torch
19
+ from torch import Tensor
20
+
21
+ from physics_informed_bo.experiment.parameter_space import ParameterSpace
22
+ from physics_informed_bo.experiment.campaign import OptimizationCampaign
23
+ from physics_informed_bo.config import OptimizationConfig, AcquisitionType
24
+
25
+
26
+ # ============================================================================
27
+ # 1. Define the physics model (simplified polymer recyclability model)
28
+ # ============================================================================
29
+
30
+ def polymer_physics_model(X: Tensor) -> Tensor:
31
+ """Simplified physics model for polymer recyclability.
32
+
33
+ Based on:
34
+ - Flory-Huggins mixing thermodynamics
35
+ - Arrhenius reaction kinetics
36
+ - Empirical catalyst efficiency model
37
+
38
+ Args:
39
+ X: Tensor of shape (n, 3) with columns:
40
+ [monomer_ratio, temperature, catalyst_loading]
41
+
42
+ Returns:
43
+ Predicted recyclability metric (higher = better).
44
+ """
45
+ ratio = X[:, 0] # monomer ratio
46
+ temp = X[:, 1] # temperature (K)
47
+ catalyst = X[:, 2] # catalyst loading (wt%)
48
+
49
+ # Flory-Huggins: optimal mixing near 50:50 ratio
50
+ chi = 0.5 - 0.3 * (ratio - 0.5) ** 2 # chi parameter
51
+ mixing_term = -ratio * torch.log(ratio + 1e-8) - (1 - ratio) * torch.log(1 - ratio + 1e-8)
52
+ mixing_free_energy = mixing_term - chi * ratio * (1 - ratio)
53
+
54
+ # Arrhenius: reaction rate dependence on temperature
55
+ Ea = 50.0 # kJ/mol activation energy
56
+ R = 8.314e-3 # kJ/(mol·K)
57
+ rate = torch.exp(-Ea / (R * temp))
58
+
59
+ # Catalyst efficiency (diminishing returns)
60
+ catalyst_eff = 1 - torch.exp(-0.8 * catalyst)
61
+
62
+ # Combined recyclability metric
63
+ recyclability = 5.0 * mixing_free_energy * rate * catalyst_eff + 2.0
64
+
65
+ return recyclability
66
+
67
+
68
+ # ============================================================================
69
+ # 2. Define the "true" function (simulates real experiments with noise)
70
+ # ============================================================================
71
+
72
+ def true_recyclability(params: dict) -> float:
73
+ """Simulate running an actual experiment (physics + discrepancy + noise)."""
74
+ X = torch.tensor(
75
+ [[params["monomer_ratio"], params["temperature"], params["catalyst_loading"]]],
76
+ dtype=torch.float64,
77
+ )
78
+
79
+ # Physics prediction
80
+ physics = polymer_physics_model(X).item()
81
+
82
+ # Add model discrepancy (physics doesn't capture everything)
83
+ ratio = params["monomer_ratio"]
84
+ temp = params["temperature"]
85
+ discrepancy = 0.3 * torch.sin(torch.tensor(10.0 * ratio)).item() \
86
+ + 0.1 * (temp - 400) / 100
87
+
88
+ # Add measurement noise
89
+ noise = 0.05 * torch.randn(1).item()
90
+
91
+ return physics + discrepancy + noise
92
+
93
+
94
+ # ============================================================================
95
+ # 3. Set up the optimization campaign
96
+ # ============================================================================
97
+
98
+ def main():
99
+ # Define parameter space
100
+ space = ParameterSpace()
101
+ space.add_continuous("monomer_ratio", 0.1, 0.9, units="ratio")
102
+ space.add_continuous("temperature", 350.0, 500.0, units="K")
103
+ space.add_continuous("catalyst_loading", 0.5, 5.0, units="wt%")
104
+
105
+ # Generate some initial experimental data
106
+ torch.manual_seed(42)
107
+ X_init = space.sample_latin_hypercube(5)
108
+ y_init = torch.tensor(
109
+ [true_recyclability(space.to_dict(X_init)[i]) for i in range(5)],
110
+ dtype=torch.float64,
111
+ ).unsqueeze(-1)
112
+
113
+ print("=== Initial Data ===")
114
+ for i, (params, y_val) in enumerate(zip(space.to_dict(X_init), y_init)):
115
+ print(f" Exp {i+1}: {params} -> {y_val.item():.4f}")
116
+
117
+ # Configure optimization
118
+ config = OptimizationConfig(
119
+ acquisition_type=AcquisitionType.PHYSICS_INFORMED_EI,
120
+ n_initial_samples=5,
121
+ max_iterations=20,
122
+ use_physics_mean=True,
123
+ noise_variance=0.01,
124
+ )
125
+
126
+ # Create campaign
127
+ campaign = OptimizationCampaign(
128
+ name="polymer_recyclability",
129
+ parameter_space=space,
130
+ physics_fn=polymer_physics_model,
131
+ initial_data=(X_init, y_init),
132
+ config=config,
133
+ maximize=True,
134
+ )
135
+
136
+ print("\n=== Running Optimization ===")
137
+
138
+ def callback(iteration, best):
139
+ print(f" Iteration {iteration}: best = {best['objective']:.4f}")
140
+
141
+ # Run automated optimization
142
+ results_df = campaign.run_automated(
143
+ objective_fn=true_recyclability,
144
+ max_iterations=15,
145
+ callback=callback,
146
+ )
147
+
148
+ # Report results
149
+ best = campaign.get_best()
150
+ print(f"\n=== Best Result ===")
151
+ print(f" Parameters: {best['parameters']}")
152
+ print(f" Objective: {best['objective']:.4f}")
153
+
154
+ print(f"\n=== Campaign Summary ===")
155
+ summary = campaign.summary()
156
+ print(f" Total experiments: {summary['n_experiments']}")
157
+ print(f" Physics model R²: {summary['model_summary'].get('model_quality', {}).get('r2', 'N/A')}")
158
+
159
+ # Save results
160
+ campaign.save("polymer_campaign.json")
161
+ results_df.to_csv("polymer_results.csv", index=False)
162
+ print("\nResults saved to polymer_campaign.json and polymer_results.csv")
163
+
164
+
165
+ if __name__ == "__main__":
166
+ main()