pinnrl 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pinnrl/__init__.py +1 -0
- pinnrl/components/adaptive_weights.py +134 -0
- pinnrl/config/__init__.py +725 -0
- pinnrl/config/config.yaml +382 -0
- pinnrl/dashboard.py +1919 -0
- pinnrl/main.py +86 -0
- pinnrl/neural_networks/__init__.py +154 -0
- pinnrl/neural_networks/attention.py +183 -0
- pinnrl/neural_networks/autoencoder.py +100 -0
- pinnrl/neural_networks/base_network.py +104 -0
- pinnrl/neural_networks/feedforward.py +73 -0
- pinnrl/neural_networks/fno.py +146 -0
- pinnrl/neural_networks/fourier.py +124 -0
- pinnrl/neural_networks/resnet.py +142 -0
- pinnrl/neural_networks/siren.py +90 -0
- pinnrl/pdes/__init__.py +49 -0
- pinnrl/pdes/allen_cahn.py +169 -0
- pinnrl/pdes/black_scholes.py +168 -0
- pinnrl/pdes/burgers_equation.py +177 -0
- pinnrl/pdes/cahn_hilliard.py +221 -0
- pinnrl/pdes/convection_equation.py +137 -0
- pinnrl/pdes/heat_equation.py +594 -0
- pinnrl/pdes/kdv_equation.py +159 -0
- pinnrl/pdes/pde_base.py +1302 -0
- pinnrl/pdes/pendulum_equation.py +289 -0
- pinnrl/pdes/wave_equation.py +187 -0
- pinnrl/rl/__init__.py +0 -0
- pinnrl/rl/rl_agent.py +748 -0
- pinnrl/training/__init__.py +5 -0
- pinnrl/training/train.py +390 -0
- pinnrl/training/trainer.py +1398 -0
- pinnrl/utils/__init__.py +23 -0
- pinnrl/utils/utils.py +795 -0
- pinnrl-0.1.0.dist-info/METADATA +276 -0
- pinnrl-0.1.0.dist-info/RECORD +38 -0
- pinnrl-0.1.0.dist-info/WHEEL +4 -0
- pinnrl-0.1.0.dist-info/entry_points.txt +2 -0
- pinnrl-0.1.0.dist-info/licenses/LICENSE +21 -0
pinnrl/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Top-level package for PINNs-RL-PDE framework."""
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import torch
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AdaptiveLossWeights:
|
|
7
|
+
"""Handles adaptive weighting of different loss components in PINNs."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, strategy="rbw", alpha=0.9, eps=1e-5, initial_weights=None):
|
|
10
|
+
"""
|
|
11
|
+
Initialize adaptive loss weights handler.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
strategy (str): Weight adaptation strategy ('lrw' or 'rbw')
|
|
15
|
+
alpha (float): Moving average factor for weight updates
|
|
16
|
+
eps (float): Small constant for numerical stability
|
|
17
|
+
initial_weights (list): Initial weights for [pde, boundary, initial] components
|
|
18
|
+
"""
|
|
19
|
+
self.strategy = strategy.lower()
|
|
20
|
+
self.alpha = alpha
|
|
21
|
+
# Ensure eps is a float, not a string
|
|
22
|
+
self.eps = float(eps) if isinstance(eps, (str, int)) else eps
|
|
23
|
+
self.initial_weights = (
|
|
24
|
+
torch.tensor(initial_weights) if initial_weights is not None else None
|
|
25
|
+
)
|
|
26
|
+
self.weights = None
|
|
27
|
+
self.running_losses = None
|
|
28
|
+
self.running_grads = None
|
|
29
|
+
self.logger = logging.getLogger(__name__)
|
|
30
|
+
self.logger.info(
|
|
31
|
+
f"AdaptiveLossWeights initialized with strategy={strategy}, alpha={alpha}, eps={self.eps}, initial_weights={initial_weights}"
|
|
32
|
+
)
|
|
33
|
+
self.prev_weights = None
|
|
34
|
+
|
|
35
|
+
def update_weights_lrw(self, gradients):
|
|
36
|
+
"""
|
|
37
|
+
Update weights using Learning Rate based Weighting (LRW).
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
gradients (list): List of gradient norms for each loss component
|
|
41
|
+
"""
|
|
42
|
+
if self.running_grads is None:
|
|
43
|
+
self.running_grads = gradients
|
|
44
|
+
self.weights = (
|
|
45
|
+
self.initial_weights.to(gradients.device)
|
|
46
|
+
if self.initial_weights is not None
|
|
47
|
+
else torch.ones_like(gradients)
|
|
48
|
+
)
|
|
49
|
+
self.logger.info(f"LRW - Initialized weights: {self.weights}")
|
|
50
|
+
return self.weights
|
|
51
|
+
|
|
52
|
+
# Update running average of gradients
|
|
53
|
+
self.running_grads = self.alpha * self.running_grads + (1 - self.alpha) * gradients
|
|
54
|
+
|
|
55
|
+
# Ensure eps is a tensor on the same device as the gradients
|
|
56
|
+
eps_tensor = torch.tensor(self.eps, device=self.running_grads.device)
|
|
57
|
+
|
|
58
|
+
# Compute weights inversely proportional to gradient magnitudes
|
|
59
|
+
inv_grads = 1.0 / (self.running_grads + eps_tensor)
|
|
60
|
+
self.weights = inv_grads / torch.sum(inv_grads)
|
|
61
|
+
|
|
62
|
+
self.logger.info(
|
|
63
|
+
f"LRW - Updated weights: gradients={gradients.detach().cpu().numpy()}, running_grads={self.running_grads.detach().cpu().numpy()}, weights={self.weights.detach().cpu().numpy()}"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return self.weights
|
|
67
|
+
|
|
68
|
+
def update_weights_rbw(self, losses):
|
|
69
|
+
"""
|
|
70
|
+
Update weights using Relative Error based Weighting (RBW).
|
|
71
|
+
Gives more weight to terms with bigger losses to balance them.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
losses (list): List of individual loss components
|
|
75
|
+
"""
|
|
76
|
+
if self.running_losses is None:
|
|
77
|
+
self.running_losses = losses
|
|
78
|
+
self.weights = (
|
|
79
|
+
self.initial_weights.to(losses.device)
|
|
80
|
+
if self.initial_weights is not None
|
|
81
|
+
else torch.ones_like(losses)
|
|
82
|
+
)
|
|
83
|
+
self.logger.info(f"RBW - Initialized weights: {self.weights}")
|
|
84
|
+
return self.weights
|
|
85
|
+
|
|
86
|
+
# Update running average of losses
|
|
87
|
+
self.running_losses = self.alpha * self.running_losses + (1 - self.alpha) * losses
|
|
88
|
+
|
|
89
|
+
# Ensure eps is a tensor on the same device as the losses
|
|
90
|
+
eps_tensor = torch.tensor(self.eps, device=self.running_losses.device)
|
|
91
|
+
|
|
92
|
+
# Normalize the running losses to get weights
|
|
93
|
+
# Give more weight to higher losses to focus optimization on problematic terms
|
|
94
|
+
normalized_losses = self.running_losses / (self.running_losses.sum() + eps_tensor)
|
|
95
|
+
self.weights = normalized_losses # Higher loss -> Higher weight
|
|
96
|
+
|
|
97
|
+
# Update weights with exponential moving average
|
|
98
|
+
if self.prev_weights is not None:
|
|
99
|
+
self.weights = self.alpha * self.prev_weights + (1 - self.alpha) * self.weights
|
|
100
|
+
|
|
101
|
+
self.prev_weights = self.weights.clone()
|
|
102
|
+
|
|
103
|
+
self.logger.info(
|
|
104
|
+
f"RBW - Updated weights: losses={losses.detach().cpu().numpy()}, running_losses={self.running_losses.detach().cpu().numpy()}, weights={self.weights.detach().cpu().numpy()}"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
return self.weights
|
|
108
|
+
|
|
109
|
+
def update(self, losses=None, gradients=None):
|
|
110
|
+
"""
|
|
111
|
+
Update weights based on chosen strategy.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
losses (list): List of individual loss components
|
|
115
|
+
gradients (list): List of gradient norms for each loss component
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
torch.Tensor: Updated loss weights
|
|
119
|
+
"""
|
|
120
|
+
if self.strategy == "lrw" and gradients is not None:
|
|
121
|
+
return self.update_weights_lrw(gradients)
|
|
122
|
+
elif self.strategy == "rbw" and losses is not None:
|
|
123
|
+
return self.update_weights_rbw(losses)
|
|
124
|
+
else:
|
|
125
|
+
raise ValueError(f"Invalid combination of strategy ({self.strategy}) and inputs")
|
|
126
|
+
|
|
127
|
+
def get_weights(self):
|
|
128
|
+
"""Return current weights."""
|
|
129
|
+
if self.weights is not None:
|
|
130
|
+
return self.weights
|
|
131
|
+
elif self.initial_weights is not None:
|
|
132
|
+
return self.initial_weights
|
|
133
|
+
else:
|
|
134
|
+
return torch.ones(3) / 3.0 # Default to equal weights for 3 components
|