|
23 | 23 | from tqdm import tqdm |
24 | 24 |
|
25 | 25 | from linopy import solvers |
| 26 | +from linopy.common import to_polars |
26 | 27 | from linopy.constants import CONCAT_DIM |
27 | 28 | from linopy.objective import Objective |
28 | 29 |
|
@@ -327,6 +328,66 @@ def integers_to_file( |
327 | 328 | formatted.write_csv(f, **kwargs) |
328 | 329 |
|
329 | 330 |
|
| 331 | +def sos_to_file( |
| 332 | + m: Model, |
| 333 | + f: BufferedWriter, |
| 334 | + progress: bool = False, |
| 335 | + slice_size: int = 2_000_000, |
| 336 | + explicit_coordinate_names: bool = False, |
| 337 | +) -> None: |
| 338 | + """ |
| 339 | + Write out integers of a model to a lp file. |
| 340 | + """ |
| 341 | + names = m.variables.sos |
| 342 | + if not len(list(names)): |
| 343 | + return |
| 344 | + |
| 345 | + print_variable, _ = get_printers( |
| 346 | + m, explicit_coordinate_names=explicit_coordinate_names |
| 347 | + ) |
| 348 | + |
| 349 | + f.write(b"\n\nsos\n\n") |
| 350 | + if progress: |
| 351 | + names = tqdm( |
| 352 | + list(names), |
| 353 | + desc="Writing sos constraints.", |
| 354 | + colour=TQDM_COLOR, |
| 355 | + ) |
| 356 | + |
| 357 | + for name in names: |
| 358 | + var = m.variables[name] |
| 359 | + sos_type = var.attrs["sos_type"] |
| 360 | + sos_dim = var.attrs["sos_dim"] |
| 361 | + |
| 362 | + other_dims = tuple([dim for dim in var.labels.dims if dim != sos_dim]) |
| 363 | + for var_slice in var.iterate_slices(slice_size, other_dims): |
| 364 | + ds = var_slice.labels.to_dataset() |
| 365 | + ds["sos_labels"] = ds["labels"].isel({sos_dim: 0}) |
| 366 | + ds["weights"] = ds.coords[sos_dim] |
| 367 | + df = to_polars(ds) |
| 368 | + |
| 369 | + df = df.group_by("sos_labels").agg( |
| 370 | + pl.concat_str( |
| 371 | + *print_variable(pl.col("labels")), pl.lit(":"), pl.col("weights") |
| 372 | + ) |
| 373 | + .str.join(" ") |
| 374 | + .alias("var_weights") |
| 375 | + ) |
| 376 | + |
| 377 | + columns = [ |
| 378 | + pl.lit("s"), |
| 379 | + pl.col("sos_labels"), |
| 380 | + pl.lit(f": S{sos_type} :: "), |
| 381 | + pl.col("var_weights"), |
| 382 | + ] |
| 383 | + |
| 384 | + kwargs: Any = dict( |
| 385 | + separator=" ", null_value="", quote_style="never", include_header=False |
| 386 | + ) |
| 387 | + formatted = df.select(pl.concat_str(columns, ignore_nulls=True)) |
| 388 | + formatted.write_csv(f, **kwargs) |
| 389 | + |
| 390 | + |
330 | 391 | def constraints_to_file( |
331 | 392 | m: Model, |
332 | 393 | f: BufferedWriter, |
@@ -464,6 +525,13 @@ def to_lp_file( |
464 | 525 | slice_size=slice_size, |
465 | 526 | explicit_coordinate_names=explicit_coordinate_names, |
466 | 527 | ) |
| 528 | + sos_to_file( |
| 529 | + m, |
| 530 | + f=f, |
| 531 | + progress=progress, |
| 532 | + slice_size=slice_size, |
| 533 | + explicit_coordinate_names=explicit_coordinate_names, |
| 534 | + ) |
467 | 535 | f.write(b"end\n") |
468 | 536 |
|
469 | 537 | logger.info(f" Writing time: {round(time.time() - start, 2)}s") |
|
0 commit comments