pyconvexity 0.3.7__py3-none-any.whl → 0.3.8.post1__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.

Potentially problematic release.


This version of pyconvexity might be problematic. Click here for more details.

pyconvexity/_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.3.7"
1
+ __version__ = "0.3.8.post1"
@@ -76,14 +76,10 @@ def solve_network(
76
76
  if progress_callback:
77
77
  progress_callback(50, f"Network built: {len(network.buses)} buses, {len(network.generators)} generators")
78
78
 
79
- # Apply constraints
79
+ # Create constraint applicator (constraints will be applied during solve via extra_functionality)
80
80
  constraint_applicator = ConstraintApplicator()
81
- if constraints_dsl or progress_callback:
82
- if progress_callback:
83
- progress_callback(60, "Applying constraints...")
84
- constraint_applicator.apply_constraints(conn, network_id, network, scenario_id, constraints_dsl)
85
81
 
86
- # Solve network
82
+ # Solve network (constraints are applied during optimization)
87
83
  if progress_callback:
88
84
  progress_callback(70, f"Solving with {solver_name}...")
89
85
 
@@ -47,6 +47,53 @@ class ConstraintApplicator:
47
47
  if constraints_dsl:
48
48
  self._apply_dsl_constraints(network, constraints_dsl)
49
49
 
50
+ def _detect_constraint_type(self, constraint_code: str) -> str:
51
+ """
52
+ Detect if constraint is network-modification or model-constraint type.
53
+
54
+ Args:
55
+ constraint_code: The constraint code to analyze
56
+
57
+ Returns:
58
+ "model_constraint" or "network_modification"
59
+ """
60
+ # Type 2 indicators (model constraints) - need access to optimization model
61
+ model_indicators = [
62
+ 'n.optimize.create_model()',
63
+ 'm.variables',
64
+ 'm.add_constraints',
65
+ 'gen_p =',
66
+ 'constraint_expr =',
67
+ 'LinearExpression',
68
+ 'linopy',
69
+ 'Generator-p',
70
+ 'lhs <=',
71
+ 'constraint_expr =',
72
+ 'model.variables',
73
+ 'model.add_constraints'
74
+ ]
75
+
76
+ # Type 1 indicators (network modifications) - modify network directly
77
+ network_indicators = [
78
+ 'n.generators.loc',
79
+ 'n.add(',
80
+ 'n.buses.',
81
+ 'n.lines.',
82
+ 'network.generators.loc',
83
+ 'network.add(',
84
+ 'network.buses.',
85
+ 'network.lines.'
86
+ ]
87
+
88
+ # Check for model constraint indicators first (more specific)
89
+ if any(indicator in constraint_code for indicator in model_indicators):
90
+ return "model_constraint"
91
+ elif any(indicator in constraint_code for indicator in network_indicators):
92
+ return "network_modification"
93
+ else:
94
+ # Default to network_modification for safety (existing behavior)
95
+ return "network_modification"
96
+
50
97
  def _apply_database_constraints(
51
98
  self,
52
99
  conn,
@@ -64,6 +111,9 @@ class ConstraintApplicator:
64
111
 
65
112
  # Load constraint attributes and filter active ones
66
113
  active_constraints = []
114
+ model_constraints = []
115
+ network_constraints = []
116
+
67
117
  for constraint in constraints:
68
118
  try:
69
119
  # Get constraint attributes
@@ -79,16 +129,12 @@ class ConstraintApplicator:
79
129
  is_active_bool = is_active.static_value.data["Boolean"]
80
130
 
81
131
  if is_active_bool:
82
- # Extract code value first to check if it's an optimization constraint
132
+ # Extract code value
83
133
  code_val = ""
84
134
  if constraint_code.variant == "Static":
85
135
  if "String" in constraint_code.static_value.data:
86
136
  code_val = constraint_code.static_value.data["String"]
87
137
 
88
- # Skip optimization-time constraints in pre-optimization phase
89
- if 'net.model' in code_val or 'network.model' in code_val or 'n.model' in code_val:
90
- continue
91
-
92
138
  # Extract priority value
93
139
  priority_val = 0
94
140
  if priority.variant == "Static":
@@ -97,48 +143,137 @@ class ConstraintApplicator:
97
143
  elif "Float" in priority.static_value.data:
98
144
  priority_val = int(priority.static_value.data["Float"])
99
145
 
100
- active_constraints.append({
146
+ constraint_dict = {
101
147
  'id': constraint.id,
102
148
  'name': constraint.name,
103
149
  'priority': priority_val,
104
- 'code': code_val
105
- })
150
+ 'code': code_val,
151
+ 'constraint_code': code_val # For compatibility
152
+ }
153
+
154
+ # Detect constraint type and separate them
155
+ constraint_type = self._detect_constraint_type(code_val)
156
+ if constraint_type == "model_constraint":
157
+ model_constraints.append(constraint_dict)
158
+ logger.info(f"Detected model constraint: {constraint.name}")
159
+ else:
160
+ network_constraints.append(constraint_dict)
161
+ logger.info(f"Detected network constraint: {constraint.name}")
106
162
 
107
163
  except Exception as e:
108
164
  logger.warning(f"Failed to load constraint {constraint.name}: {e}")
109
165
  continue
110
166
 
111
- if not active_constraints:
167
+ if not model_constraints and not network_constraints:
112
168
  return
113
169
 
114
- # Sort constraints by priority (lower numbers first)
115
- active_constraints.sort(key=lambda x: x['priority'])
170
+ logger.info(f"Constraint breakdown: {len(model_constraints)} model constraints, {len(network_constraints)} network constraints")
171
+
172
+ # Apply network constraints first (they modify the network structure)
173
+ if network_constraints:
174
+ network_constraints.sort(key=lambda x: x['priority'])
175
+ for constraint in network_constraints:
176
+ try:
177
+ logger.info(f"Executing network constraint '{constraint['name']}' (priority {constraint['priority']})")
178
+
179
+ # Execute the constraint code in the normal Python environment
180
+ exec_globals = {
181
+ 'n': network,
182
+ 'network': network,
183
+ 'pd': pd,
184
+ 'np': np,
185
+ }
186
+
187
+ # Execute the constraint code
188
+ exec(constraint['code'], exec_globals)
189
+
190
+ except Exception as e:
191
+ error_msg = f"Failed to execute network constraint '{constraint['name']}': {e}"
192
+ logger.error(error_msg, exc_info=True)
193
+ # Continue with other constraints instead of failing the entire solve
194
+ continue
195
+
196
+ # Apply model constraints (they need access to the optimization model)
197
+ if model_constraints:
198
+ self._apply_model_constraints(network, model_constraints)
199
+
200
+ except Exception as e:
201
+ logger.error(f"Failed to apply custom constraints: {e}", exc_info=True)
202
+
203
+ def _apply_model_constraints(self, network: 'pypsa.Network', model_constraints: list):
204
+ """
205
+ Apply model constraints that need access to the optimization model.
206
+
207
+ This creates the optimization model, applies constraints to it, and then
208
+ replaces PyPSA's solve method to use the pre-constrained model.
209
+
210
+ Args:
211
+ network: PyPSA Network object
212
+ model_constraints: List of model constraint dictionaries
213
+ """
214
+ try:
215
+ logger.info(f"Applying {len(model_constraints)} model constraints...")
216
+
217
+ # Create the optimization model (same as PyPSA would do internally)
218
+ logger.info("Creating optimization model for constraint application...")
219
+ model = network.optimize.create_model()
220
+ logger.info(f"Created optimization model with {len(model.variables)} variable groups")
116
221
 
117
- # Execute constraints in order
118
- for constraint in active_constraints:
222
+ # Sort constraints by priority
223
+ sorted_constraints = sorted(model_constraints, key=lambda x: x['priority'])
224
+
225
+ # Apply each model constraint
226
+ for constraint in sorted_constraints:
119
227
  try:
120
- logger.info(f"Executing constraint '{constraint['name']}' (priority {constraint['priority']})")
121
- logger.debug(f"Code: {constraint['code']}")
228
+ constraint_code = constraint['constraint_code']
229
+ constraint_name = constraint['name']
122
230
 
123
- # Execute the constraint code in the normal Python environment
124
- # The network object 'n' is available in the global scope
231
+ logger.info(f"Applying model constraint '{constraint_name}' (priority {constraint['priority']})")
232
+
233
+ # Create execution environment with network, model, and utilities
125
234
  exec_globals = {
126
235
  'n': network,
236
+ 'network': network,
237
+ 'model': model,
238
+ 'm': model,
239
+ 'snapshots': network.snapshots,
127
240
  'pd': pd,
128
241
  'np': np,
242
+ 'xr': __import__('xarray'), # Import xarray for DataArray operations
129
243
  }
130
244
 
131
245
  # Execute the constraint code
132
- exec(constraint['code'], exec_globals)
246
+ exec(constraint_code, exec_globals)
247
+ logger.info(f"Successfully applied model constraint '{constraint_name}'")
133
248
 
134
249
  except Exception as e:
135
- error_msg = f"Failed to execute constraint '{constraint['name']}': {e}"
250
+ error_msg = f"Failed to apply model constraint '{constraint.get('name', 'unknown')}': {e}"
136
251
  logger.error(error_msg, exc_info=True)
137
- # Continue with other constraints instead of failing the entire solve
252
+ # Continue with other constraints instead of failing
138
253
  continue
139
-
254
+
255
+ # Store the constrained model for the solver to use
256
+ # We'll replace PyPSA's solve_model method to use our pre-constrained model
257
+ logger.info("Replacing PyPSA's solve method to use pre-constrained model...")
258
+
259
+ # Store original methods
260
+ original_optimize = network.optimize
261
+ original_solve_model = original_optimize.solve_model
262
+
263
+ # Create a wrapper that uses our pre-constrained model
264
+ def constrained_solve_model(*args, **kwargs):
265
+ """Use the pre-constrained model instead of creating a new one."""
266
+ logger.info("Using pre-constrained model for solve...")
267
+ return original_solve_model(model, *args, **kwargs)
268
+
269
+ # Replace the solve_model method
270
+ network.optimize.solve_model = constrained_solve_model
271
+
272
+ logger.info(f"Successfully applied {len(model_constraints)} model constraints")
273
+
140
274
  except Exception as e:
141
- logger.error(f"Failed to apply custom constraints: {e}", exc_info=True)
275
+ logger.error(f"Failed to apply model constraints: {e}", exc_info=True)
276
+ # Don't re-raise - let the solve continue without constraints rather than fail completely
142
277
 
143
278
  def _apply_dsl_constraints(self, network: 'pypsa.Network', constraints_dsl: str):
144
279
  """
@@ -172,7 +307,8 @@ class ConstraintApplicator:
172
307
  scenario_id: Optional[int] = None
173
308
  ) -> List[Dict[str, Any]]:
174
309
  """
175
- Get constraints that need to be applied during optimization (via extra_functionality).
310
+ Get ALL active constraints for optimization-time application.
311
+ The solver will determine which are model constraints vs network constraints.
176
312
 
177
313
  Args:
178
314
  conn: Database connection
@@ -180,7 +316,7 @@ class ConstraintApplicator:
180
316
  scenario_id: Optional scenario ID
181
317
 
182
318
  Returns:
183
- List of optimization constraints
319
+ List of all active constraints
184
320
  """
185
321
  try:
186
322
  # Load all constraints for this network
@@ -189,7 +325,7 @@ class ConstraintApplicator:
189
325
  if not constraints:
190
326
  return []
191
327
 
192
- # Load constraint attributes and filter active optimization-time ones
328
+ # Load constraint attributes and filter active ones
193
329
  optimization_constraints = []
194
330
  for constraint in constraints:
195
331
  try:
@@ -212,26 +348,24 @@ class ConstraintApplicator:
212
348
  if "String" in constraint_code.static_value.data:
213
349
  code_val = constraint_code.static_value.data["String"]
214
350
 
215
- # Check if this is an optimization-time constraint
216
- # (contains model access patterns like 'net.model' or 'network.model')
217
- if 'net.model' in code_val or 'network.model' in code_val or 'n.model' in code_val:
218
- # Extract priority value
219
- priority_val = 0
220
- if priority.variant == "Static":
221
- if "Integer" in priority.static_value.data:
222
- priority_val = priority.static_value.data["Integer"]
223
- elif "Float" in priority.static_value.data:
224
- priority_val = int(priority.static_value.data["Float"])
225
-
226
- optimization_constraints.append({
227
- 'id': constraint.id,
228
- 'name': constraint.name,
229
- 'priority': priority_val,
230
- 'code': code_val
231
- })
351
+ # Extract priority value
352
+ priority_val = 0
353
+ if priority.variant == "Static":
354
+ if "Integer" in priority.static_value.data:
355
+ priority_val = priority.static_value.data["Integer"]
356
+ elif "Float" in priority.static_value.data:
357
+ priority_val = int(priority.static_value.data["Float"])
358
+
359
+ optimization_constraints.append({
360
+ 'id': constraint.id,
361
+ 'name': constraint.name,
362
+ 'priority': priority_val,
363
+ 'constraint_code': code_val, # Use consistent key name
364
+ 'code': code_val # Keep both for compatibility
365
+ })
232
366
 
233
367
  except Exception as e:
234
- logger.warning(f"Failed to load optimization constraint {constraint.name}: {e}")
368
+ logger.warning(f"Failed to load constraint {constraint.name}: {e}")
235
369
  continue
236
370
 
237
371
  # Sort constraints by priority (lower numbers first)
@@ -310,6 +444,7 @@ class ConstraintApplicator:
310
444
  'snapshots': snapshots,
311
445
  'pd': pd,
312
446
  'np': np,
447
+ 'xr': __import__('xarray'),
313
448
  }
314
449
 
315
450
  # Execute the constraint code
@@ -139,13 +139,39 @@ class NetworkSolver:
139
139
  if conn and network_id:
140
140
  self._set_snapshot_weightings_after_multiperiod(conn, network_id, network)
141
141
 
142
- # Prepare optimization constraints (extra_functionality)
142
+ # Prepare optimization constraints with type detection
143
143
  extra_functionality = None
144
+ model_constraints = []
145
+ network_constraints = []
146
+
144
147
  if conn and network_id and constraint_applicator:
145
148
  optimization_constraints = constraint_applicator.get_optimization_constraints(conn, network_id, scenario_id)
146
149
  if optimization_constraints:
147
- logger.info(f"Applying {len(optimization_constraints)} optimization-time constraints")
148
- extra_functionality = self._create_extra_functionality(optimization_constraints, constraint_applicator)
150
+ logger.info(f"Found {len(optimization_constraints)} optimization constraints")
151
+
152
+ # Separate constraints by type
153
+ for constraint in optimization_constraints:
154
+ constraint_code = constraint.get('constraint_code', '')
155
+ constraint_type = self._detect_constraint_type(constraint_code)
156
+ constraint_name = constraint.get('name', 'unknown')
157
+
158
+ if constraint_type == "model_constraint":
159
+ model_constraints.append(constraint)
160
+ logger.info(f"Detected model constraint: {constraint_name}")
161
+ else:
162
+ network_constraints.append(constraint)
163
+ logger.info(f"Detected network constraint: {constraint_name}")
164
+
165
+ logger.info(f"Constraint breakdown: {len(model_constraints)} model constraints, {len(network_constraints)} network constraints")
166
+
167
+ # Create extra_functionality for ALL constraints (both model and network)
168
+ all_constraints = model_constraints + network_constraints
169
+ if all_constraints:
170
+ extra_functionality = self._create_extra_functionality(all_constraints, constraint_applicator)
171
+ logger.info(f"Prepared {len(all_constraints)} constraints for optimization-time application")
172
+
173
+ # NOTE: Model constraints are now applied DURING solve via extra_functionality
174
+ # This ensures they are applied to the actual model PyPSA creates, not a separate model
149
175
 
150
176
  # Solver diagnostics
151
177
  logger.info(f"=== PYPSA SOLVER DIAGNOSTICS ===")
@@ -342,7 +368,7 @@ class NetworkSolver:
342
368
  return 'gurobi', gurobi_dual_options
343
369
 
344
370
  # Check if this is a known valid solver name
345
- elif solver_name in ['highs', 'gurobi', 'cplex', 'glpk', 'cbc', 'scip']:
371
+ elif solver_name in ['highs', 'gurobi', 'cplex', 'glpk', 'cbc', 'scip', 'copt']:
346
372
  return solver_name, solver_options
347
373
 
348
374
  else:
@@ -351,6 +377,51 @@ class NetworkSolver:
351
377
  return 'highs', solver_options
352
378
 
353
379
 
380
+ def _detect_constraint_type(self, constraint_code: str) -> str:
381
+ """
382
+ Detect if constraint is network-modification or model-constraint type.
383
+
384
+ Args:
385
+ constraint_code: The constraint code to analyze
386
+
387
+ Returns:
388
+ "model_constraint" or "network_modification"
389
+ """
390
+ # Type 2 indicators (model constraints) - need access to optimization model
391
+ model_indicators = [
392
+ 'n.optimize.create_model()',
393
+ 'm.variables',
394
+ 'm.add_constraints',
395
+ 'gen_p =',
396
+ 'constraint_expr =',
397
+ 'LinearExpression',
398
+ 'linopy',
399
+ 'Generator-p',
400
+ 'lhs <=',
401
+ 'constraint_expr ='
402
+ ]
403
+
404
+ # Type 1 indicators (network modifications) - modify network directly
405
+ network_indicators = [
406
+ 'n.generators.loc',
407
+ 'n.add(',
408
+ 'n.buses.',
409
+ 'n.lines.',
410
+ 'network.generators.loc',
411
+ 'network.add(',
412
+ 'network.buses.',
413
+ 'network.lines.'
414
+ ]
415
+
416
+ # Check for model constraint indicators first (more specific)
417
+ if any(indicator in constraint_code for indicator in model_indicators):
418
+ return "model_constraint"
419
+ elif any(indicator in constraint_code for indicator in network_indicators):
420
+ return "network_modification"
421
+ else:
422
+ # Default to network_modification for safety (existing behavior)
423
+ return "network_modification"
424
+
354
425
  def _create_extra_functionality(self, optimization_constraints: list, constraint_applicator) -> callable:
355
426
  """
356
427
  Create extra_functionality function for optimization-time constraints.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyconvexity
3
- Version: 0.3.7
3
+ Version: 0.3.8.post1
4
4
  Summary: Python library for energy system modeling and optimization with PyPSA
5
5
  Author-email: Convexity Team <info@convexity.com>
6
6
  License: MIT
@@ -1,5 +1,5 @@
1
1
  pyconvexity/__init__.py,sha256=eiAFroO4n-z8F0jTLpJgBIO7vtSxu9ovu3G2N-qqpUo,4783
2
- pyconvexity/_version.py,sha256=J0I0c7-a50EOnWXMryTu_E6xhXSYFBPjVpeYP_a3vRI,22
2
+ pyconvexity/_version.py,sha256=bzpt5I55RpJ9-TikkLRgUK3tzieEqyUA-wVI8qcMUx0,28
3
3
  pyconvexity/timeseries.py,sha256=4p1Tdpa1otqDvCq2zppA4tw660sF_XWb8Xobib-cCms,11340
4
4
  pyconvexity/core/__init__.py,sha256=MgVa5rrRWIi2w1UI1P4leiBntvHeeOPv0Thm0DEXBHo,1209
5
5
  pyconvexity/core/database.py,sha256=M02q4UkJqAPeTXuwng9I7kHm16reJ7eq7wccWxnhE5I,15227
@@ -7,14 +7,19 @@ pyconvexity/core/errors.py,sha256=HhrrOOEBJrzyB56_pmqh3NWvX6uHqWWNkdE5XM16rYI,28
7
7
  pyconvexity/core/types.py,sha256=LkB49qklA-9ObI0br0IazfVxvWvYzQrYMdwzrqqAMYQ,11335
8
8
  pyconvexity/data/README.md,sha256=-tyDHVjqzfWbVvgM4yYYx8cysmgvFXI6plVQNxSHBmo,3156
9
9
  pyconvexity/data/__init__.py,sha256=BrgC3LGSlReLbC0EpM6UxywwUHxRvts379CvZFE0qWU,514
10
+ pyconvexity/data/__pycache__/__init__.cpython-313.pyc,sha256=F2XXlQZlN5aoFmi7Ar1B3RW-DZjIUqp81fr3zNsPxpY,617
10
11
  pyconvexity/data/loaders/__init__.py,sha256=6xPtOmH2n1mNby7ZjA-2Mk9F48Q246RNsyMnCnJ6gwA,60
11
12
  pyconvexity/data/loaders/cache.py,sha256=nnz8bV3slSehOT0alexFga9tM1XoJqWHBGqaXvz132U,7299
13
+ pyconvexity/data/loaders/__pycache__/__init__.cpython-313.pyc,sha256=AuT3aXy3v5gssxdD1_CBaKqNAVmDt6GBwFSyAe3jHow,265
14
+ pyconvexity/data/loaders/__pycache__/cache.cpython-313.pyc,sha256=9_xMQN6AciMzbzhCmWAzvEKRXfRINmfRsO8Dyg0_CUQ,9804
12
15
  pyconvexity/data/schema/01_core_schema.sql,sha256=Ww3eD71JGIBNw-t_eVJ6TVGju-sEDzpLqyRGqGDje54,18871
13
16
  pyconvexity/data/schema/02_data_metadata.sql,sha256=oOfwa3PLY2_8rxKDD4cpDeqP5I_PdahcF8m6cSKStJM,10732
14
17
  pyconvexity/data/schema/03_validation_data.sql,sha256=1rKFi9y6jQ2OnfH32jnIKnZ5WtB8eG43hz0OVJhwn3w,58325
15
18
  pyconvexity/data/schema/04_scenario_schema.sql,sha256=sL4PySJNHIthXsnoJ2T5pdXUbpAi94ld0XGuU8LwNuQ,4641
16
19
  pyconvexity/data/sources/__init__.py,sha256=Dn6_oS7wB-vLjMj2YeXlmIl6hNjACbicimSabKxIWnc,108
17
20
  pyconvexity/data/sources/gem.py,sha256=Ft2pAYsWe1V9poRge2Q4xdNt15XkG-USSR0XR9KFmsY,14935
21
+ pyconvexity/data/sources/__pycache__/__init__.cpython-313.pyc,sha256=9x5FyLxmTE5ZRaEFNSF375KBd_rDLY6pGHGSWPpcxxA,313
22
+ pyconvexity/data/sources/__pycache__/gem.cpython-313.pyc,sha256=VA7v6miTbKJcSMwKElsRKwuyGP3ek95O3ALa133Lx_U,14476
18
23
  pyconvexity/io/__init__.py,sha256=glGzXBRGHROrTS8xe-RTGyRQUgsaksafxXVt9GpW63E,803
19
24
  pyconvexity/io/excel_exporter.py,sha256=pjgvTs5vq9K61mNOVutEzaH5Zx4FgrDG4Xc_YmXhE5o,48483
20
25
  pyconvexity/io/excel_importer.py,sha256=M7YcBqKUVzOMoR5HN-v8M2UnZgHRfhqgXBMUVD10-IQ,56898
@@ -27,15 +32,15 @@ pyconvexity/models/network.py,sha256=ePydR3l60-AaOBbrA4uld3hu3X9sB7GOSyBYMh3_rBA
27
32
  pyconvexity/models/scenarios.py,sha256=6-devNWZccnFeQr3IsP19GkO6Ixp914RKD-6lIduN-A,5164
28
33
  pyconvexity/solvers/__init__.py,sha256=zoVf6T2Tmyj2XOeiVbEvaIMOX584orqCz1q9t1oXy0M,674
29
34
  pyconvexity/solvers/pypsa/__init__.py,sha256=KZqYDo7CvwB-5Kp784xxxtdn5kRcmn3gGSRlaQdDA4c,554
30
- pyconvexity/solvers/pypsa/api.py,sha256=u1MTSZkCxXMukSUQ83oDz_pWf4kRXKV_Bk7b0yd7lV4,16762
35
+ pyconvexity/solvers/pypsa/api.py,sha256=05IN6KgjpVNJ3TrH0gv1F2-GLRnffLQOc3rsT1ZEql8,16629
31
36
  pyconvexity/solvers/pypsa/batch_loader.py,sha256=eQb8B11akQYtH3aK93WAOoXEI-ktk4imATw9gaYDNR4,13547
32
37
  pyconvexity/solvers/pypsa/builder.py,sha256=WrimcBvG4mNFLTrLq7131Ku0AXY_0oRKxfI81ywc5Cs,24460
33
- pyconvexity/solvers/pypsa/constraints.py,sha256=uX0X_EDFak7YtnjgNxj3CSv1nxDQI-fT4eg9lyySAv4,13678
34
- pyconvexity/solvers/pypsa/solver.py,sha256=NFZ4_8inW-xHkv7pTrfq09vkKFINDwdTuJAQTn8lMfg,54555
38
+ pyconvexity/solvers/pypsa/constraints.py,sha256=MycS-pvuYIEEa0s2tkskiydX_HhAKNTnsQdVc842u50,19792
39
+ pyconvexity/solvers/pypsa/solver.py,sha256=PA0_S95JQm6ZifuY_TEjRvEhm-zgmtZsap5G1TEHBVA,57739
35
40
  pyconvexity/solvers/pypsa/storage.py,sha256=T-0qEryiEy_8G4KiscPoiiWvTPd_OGqpLczW0_Xm85E,87331
36
41
  pyconvexity/validation/__init__.py,sha256=_6SVqXkaDFqmagub_O064Zm_QIdBrOra-Gvvbo9vM4I,549
37
42
  pyconvexity/validation/rules.py,sha256=6Kak12BVfUpjmgB5B7Wre55eGc5e1dvIdFca-vN-IFI,9296
38
- pyconvexity-0.3.7.dist-info/METADATA,sha256=sSqe9fkreaNnzTbxlms2n96Tp1wKwbGghQ60LEiP0uY,4880
39
- pyconvexity-0.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
40
- pyconvexity-0.3.7.dist-info/top_level.txt,sha256=wFPEDXVaebR3JO5Tt3HNse-ws5aROCcxEco15d6j64s,12
41
- pyconvexity-0.3.7.dist-info/RECORD,,
43
+ pyconvexity-0.3.8.post1.dist-info/METADATA,sha256=XAs5-GMZ1W6GM8E-aPhdO78v-sg5Ko-fmQGWFXueXN8,4886
44
+ pyconvexity-0.3.8.post1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ pyconvexity-0.3.8.post1.dist-info/top_level.txt,sha256=wFPEDXVaebR3JO5Tt3HNse-ws5aROCcxEco15d6j64s,12
46
+ pyconvexity-0.3.8.post1.dist-info/RECORD,,