omniopt2 8366__py3-none-any.whl → 9061__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 omniopt2 might be problematic. Click here for more details.

Files changed (48) hide show
  1. .gitignore +2 -0
  2. .helpers.py +0 -9
  3. .omniopt.py +1369 -1011
  4. .pareto.py +134 -0
  5. .shellscript_functions +2 -2
  6. .tests/pylint.rc +0 -4
  7. .tpe.py +4 -3
  8. omniopt +56 -27
  9. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.helpers.py +0 -9
  10. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt.py +1369 -1011
  11. omniopt2-9061.data/data/bin/.pareto.py +134 -0
  12. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.shellscript_functions +2 -2
  13. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.tpe.py +4 -3
  14. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt +56 -27
  15. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/pylint.rc +0 -4
  16. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/requirements.txt +1 -2
  17. {omniopt2-8366.dist-info → omniopt2-9061.dist-info}/METADATA +2 -3
  18. omniopt2-9061.dist-info/RECORD +73 -0
  19. omniopt2.egg-info/PKG-INFO +2 -3
  20. omniopt2.egg-info/SOURCES.txt +1 -0
  21. omniopt2.egg-info/requires.txt +1 -2
  22. pyproject.toml +1 -1
  23. requirements.txt +1 -2
  24. omniopt2-8366.dist-info/RECORD +0 -71
  25. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.colorfunctions.sh +0 -0
  26. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.general.sh +0 -0
  27. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_cpu_ram_usage.py +0 -0
  28. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_general.py +0 -0
  29. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_gpu_usage.py +0 -0
  30. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_kde.py +0 -0
  31. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_scatter.py +0 -0
  32. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_scatter_generation_method.py +0 -0
  33. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_scatter_hex.py +0 -0
  34. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_time_and_exit_code.py +0 -0
  35. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_trial_index_result.py +0 -0
  36. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.omniopt_plot_worker.py +0 -0
  37. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/.random_generator.py +0 -0
  38. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/LICENSE +0 -0
  39. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/apt-dependencies.txt +0 -0
  40. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt_docker +0 -0
  41. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt_evaluate +0 -0
  42. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt_plot +0 -0
  43. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/omniopt_share +0 -0
  44. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/setup.py +0 -0
  45. {omniopt2-8366.data → omniopt2-9061.data}/data/bin/test_requirements.txt +0 -0
  46. {omniopt2-8366.dist-info → omniopt2-9061.dist-info}/WHEEL +0 -0
  47. {omniopt2-8366.dist-info → omniopt2-9061.dist-info}/licenses/LICENSE +0 -0
  48. {omniopt2-8366.dist-info → omniopt2-9061.dist-info}/top_level.txt +0 -0
.pareto.py ADDED
@@ -0,0 +1,134 @@
1
+ import os
2
+ import importlib.util
3
+ from typing import Tuple, List, Dict, Any
4
+ from rich.table import Table
5
+ from rich.text import Text
6
+ import numpy as np
7
+
8
+
9
+ # ----------------- Helpers import -----------------
10
+ script_dir = os.path.dirname(os.path.realpath(__file__))
11
+ helpers_file: str = f"{script_dir}/.helpers.py"
12
+ spec = importlib.util.spec_from_file_location(
13
+ name="helpers",
14
+ location=helpers_file,
15
+ )
16
+ if spec is not None and spec.loader is not None:
17
+ helpers = importlib.util.module_from_spec(spec)
18
+ spec.loader.exec_module(helpers)
19
+ else:
20
+ raise ImportError(f"Could not load module from {helpers_file}")
21
+
22
+ # ----------------- Table utilities -----------------
23
+ def pareto_front_table_filter_rows(rows: List[Dict[str, str]], idxs: List[int]) -> List[Dict[str, str]]:
24
+ result = []
25
+ for row in rows:
26
+ try:
27
+ trial_index = int(row["trial_index"])
28
+ except (KeyError, ValueError):
29
+ continue
30
+
31
+ if row.get("trial_status", "").strip().upper() == "COMPLETED" and trial_index in idxs:
32
+ result.append(row)
33
+ return result
34
+
35
+ def pareto_front_table_add_headers(table: Table, param_cols: List[str], result_cols: List[str]) -> None:
36
+ for col in param_cols:
37
+ table.add_column(col, justify="center")
38
+ for col in result_cols:
39
+ table.add_column(Text(f"{col}", style="cyan"), justify="center")
40
+
41
+ def pareto_front_table_add_rows(table: Table, rows: List[Dict[str, str]], param_cols: List[str], result_cols: List[str]) -> None:
42
+ for row in rows:
43
+ values = [str(helpers.to_int_when_possible(row[col])) for col in param_cols]
44
+ result_values = [Text(str(helpers.to_int_when_possible(row[col])), style="cyan") for col in result_cols]
45
+ table.add_row(*values, *result_values, style="bold green")
46
+
47
+ # ----------------- Pareto internal utilities -----------------
48
+ def _validate_xy(x: np.ndarray, y: np.ndarray) -> None:
49
+ if x.shape != y.shape:
50
+ raise ValueError("Input arrays x and y must have the same shape.")
51
+ if x.size == 0:
52
+ raise ValueError("Input arrays must not be empty.")
53
+ if not np.isfinite(x).all() or not np.isfinite(y).all():
54
+ raise ValueError("Input arrays must contain only finite numbers (no NaN/Inf).")
55
+
56
+ def _point_dominates(xi: float, yi: float, xj: float, yj: float, x_minimize: bool, y_minimize: bool) -> bool:
57
+ """Return True if j dominates i (standard weak Pareto: >= in all, > in at least one)."""
58
+ if x_minimize:
59
+ x_better_eq = xj <= xi
60
+ x_strict = xj < xi
61
+ else:
62
+ x_better_eq = xj >= xi
63
+ x_strict = xj > xi
64
+
65
+ if y_minimize:
66
+ y_better_eq = yj <= yi
67
+ y_strict = yj < yi
68
+ else:
69
+ y_better_eq = yj >= yi
70
+ y_strict = yj > yi
71
+
72
+ return x_better_eq and y_better_eq and (x_strict or y_strict)
73
+
74
+ def _find_dominated(x: np.ndarray, y: np.ndarray, x_minimize: bool, y_minimize: bool) -> np.ndarray:
75
+ n = len(x)
76
+ is_dominated = np.zeros(n, dtype=bool)
77
+ for i in range(n):
78
+ if is_dominated[i]:
79
+ continue
80
+ xi, yi = x[i], y[i]
81
+ for j in range(n):
82
+ if i == j:
83
+ continue
84
+ xj, yj = x[j], y[j]
85
+ if _point_dominates(xi, yi, xj, yj, x_minimize, y_minimize):
86
+ is_dominated[i] = True
87
+ break
88
+ return is_dominated
89
+
90
+ # ----------------- Public Pareto functions -----------------
91
+ def pareto_front_general(
92
+ x: np.ndarray,
93
+ y: np.ndarray,
94
+ x_minimize: bool = True,
95
+ y_minimize: bool = True
96
+ ) -> np.ndarray:
97
+ try:
98
+ xa = np.asarray(x, dtype=float).ravel()
99
+ ya = np.asarray(y, dtype=float).ravel()
100
+ _validate_xy(xa, ya)
101
+ is_dominated = _find_dominated(xa, ya, x_minimize, y_minimize)
102
+ return np.where(~is_dominated)[0]
103
+ except Exception as e:
104
+ print("Error in pareto_front_general:", str(e))
105
+ return np.array([], dtype=int)
106
+
107
+ def pareto_front_filter_complete_points(
108
+ path_to_calculate: str,
109
+ records: Dict[Tuple[int, str], Dict[str, Dict[str, float]]],
110
+ primary_name: str,
111
+ secondary_name: str
112
+ ) -> List[Tuple[Tuple[int, str], float, float]]:
113
+ points = []
114
+ for key, metrics in records.items():
115
+ means = metrics['means']
116
+ if primary_name in means and secondary_name in means:
117
+ points.append((key, means[primary_name], means[secondary_name]))
118
+ if len(points) == 0:
119
+ raise ValueError(f"No full data points with both objectives found in {path_to_calculate}.")
120
+ return points
121
+
122
+ def pareto_front_select_pareto_points(
123
+ x: np.ndarray,
124
+ y: np.ndarray,
125
+ x_minimize: bool,
126
+ y_minimize: bool,
127
+ points: List[Tuple[Any, float, float]],
128
+ num_points: int
129
+ ) -> List[Tuple[Any, float, float]]:
130
+ indices = pareto_front_general(x, y, x_minimize, y_minimize)
131
+ # Sort by x ascending
132
+ sorted_indices = indices[np.argsort(x[indices])]
133
+ selected_points = [points[i] for i in sorted_indices[:num_points]]
134
+ return selected_points
.shellscript_functions CHANGED
@@ -266,7 +266,7 @@
266
266
 
267
267
  if [[ -z $DEBUG ]]; then
268
268
  pip3 --disable-pip-version-check install -q $MODULE >&2 2>> $INSTALL_ERRORS_FILE || pip3 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || {
269
- red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE"
269
+ red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE\n"
270
270
 
271
271
  if [[ -n $CI ]] || { [[ -f /proc/self/cgroup ]] && grep -qE '/docker|/lxc' /proc/self/cgroup; }; then
272
272
  cat "$INSTALL_ERRORS_FILE"
@@ -276,7 +276,7 @@
276
276
  }
277
277
  else
278
278
  pip3 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || pip3 --disable-pip-version-check install $MODULE >&2 2>> $INSTALL_ERRORS_FILE || {
279
- red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE"
279
+ red_reset_line "❌Failed to install $MODULE. Check $INSTALL_ERRORS_FILE\n"
280
280
 
281
281
  if [[ -n $CI ]] || { [[ -f /proc/self/cgroup ]] && grep -qE '/docker|/lxc' /proc/self/cgroup; }; then
282
282
  cat "$INSTALL_ERRORS_FILE"
.tests/pylint.rc CHANGED
@@ -103,10 +103,6 @@ recursive=no
103
103
  # source root.
104
104
  source-roots=
105
105
 
106
- # When enabled, pylint would attempt to guess common misconfiguration and emit
107
- # user-friendly hints instead of false-positive error messages.
108
- suggestion-mode=yes
109
-
110
106
  # Allow loading of arbitrary C extensions. Extensions are imported into the
111
107
  # active Python interpreter and may run arbitrary code.
112
108
  unsafe-load-any-extension=no
.tpe.py CHANGED
@@ -2,7 +2,8 @@ import sys
2
2
  import os
3
3
  import json
4
4
  import logging
5
- from typing import Optional
5
+ from typing import Optional, Any
6
+
6
7
  try:
7
8
  import optuna
8
9
  from optuna.trial import create_trial
@@ -52,7 +53,7 @@ def tpe_suggest_point(trial: optuna.Trial, parameters: dict) -> dict:
52
53
  if pvaltype == 'INT':
53
54
  point[param_name] = trial.suggest_int(param_name, rmin, rmax)
54
55
  elif pvaltype == 'FLOAT':
55
- point[param_name] = trial.suggest_float(param_name, rmin, rmax)
56
+ point[param_name] = trial.suggest_float(param_name, rmin, rmax) # type: ignore[assignment]
56
57
  else:
57
58
  raise ValueError(f"Unsupported type {pvaltype} for RANGE")
58
59
 
@@ -162,7 +163,7 @@ def add_existing_trial_to_study(study: optuna.study.study.Study, trial_entry: li
162
163
  )
163
164
 
164
165
  @beartype
165
- def get_best_or_new_point(study: optuna.study.study.Study, parameters: dict, direction: str) -> dict:
166
+ def get_best_or_new_point(study: Any, parameters: dict, direction: str) -> dict:
166
167
  best_trial_value = study.best_trial.value
167
168
  if best_trial_value is not None:
168
169
  if (direction == "minimize" and best_trial_value < 1e6) or \
omniopt CHANGED
@@ -346,10 +346,35 @@
346
346
  send_anonymized_usage_stats=0
347
347
  already_shown_oo_base_url_msg=0
348
348
 
349
+ function run_live_share {
350
+ if [[ $RUN_UUID != "" ]]; then
351
+ full_log_file="$ORIGINAL_PWD/logs/$RUN_UUID"
352
+ if [[ -e "$full_log_file" ]]; then
353
+ set +e
354
+ run_folder=$(cat "$full_log_file" | grep "Run-folder:" | sed -e 's#Run-folder: ##')
355
+ if [[ -z $run_folder ]]; then
356
+ true
357
+ else
358
+ bash "$SCRIPT_DIR/omniopt_share" --username="$USER" "$run_folder" 2>/dev/null >/dev/null
359
+ fi
360
+ set -e
361
+ else
362
+ red_text "--live_share enabled, but $full_log_file could not be found. Cannot share once again in finalization.\n"
363
+ fi
364
+ fi
365
+ }
366
+
367
+ function start_periodidic_live_share {
368
+ while true; do
369
+ run_live_share 2>/dev/null >/dev/null
370
+ sleep 10
371
+ done
372
+ }
373
+
349
374
  function myexit {
350
375
  CODE=$1
351
376
 
352
- end_all_bg_processes
377
+ end_all_bg_processes 2>/dev/null
353
378
 
354
379
  if [[ $follow -eq 1 ]]; then
355
380
  if [[ -z $CODE ]] || ! [[ $CODE =~ $int_re ]]; then
@@ -382,21 +407,7 @@
382
407
 
383
408
  if [[ $follow -eq 1 ]] || ! command -v sbatch 2>/dev/null >/dev/null || [[ $force_local_execution -eq 1 ]]; then
384
409
  if [[ $live_share -eq 1 ]]; then
385
- if [[ $RUN_UUID != "" ]]; then
386
- full_log_file="$ORIGINAL_PWD/logs/$RUN_UUID"
387
- if [[ -e "$full_log_file" ]]; then
388
- set +e
389
- run_folder=$(cat "$full_log_file" | grep "Run-folder:" | sed -e 's#Run-folder: ##')
390
- if [[ -z $run_folder ]]; then
391
- true
392
- else
393
- bash "$SCRIPT_DIR/omniopt_share" --username="$USER" "$run_folder" 2>/dev/null >/dev/null
394
- fi
395
- set -e
396
- else
397
- red_text "--live_share enabled, but $full_log_file could not be found. Cannot share once again in finalization.\n"
398
- fi
399
- fi
410
+ run_live_share
400
411
  fi
401
412
  fi
402
413
 
@@ -1005,6 +1016,10 @@ $complex_options_str
1005
1016
  args_string+=" --help "
1006
1017
  ;;
1007
1018
 
1019
+ --memray)
1020
+ export RUN_WITH_MEMRAY=1
1021
+ ;;
1022
+
1008
1023
  --flame_graph)
1009
1024
  export RUN_WITH_PYSPY=1
1010
1025
  ;;
@@ -1620,15 +1635,30 @@ EOF
1620
1635
  set +e
1621
1636
  trap - ERR
1622
1637
 
1638
+ live_share_pid=""
1639
+
1640
+ if [[ $live_share -eq 1 ]]; then
1641
+ start_periodidic_live_share &
1642
+ live_share_pid=$!
1643
+ fi
1644
+
1623
1645
  if [[ -z $RUN_WITH_COVERAGE ]]; then
1624
- if [[ -z $RUN_WITH_PYSPY ]]; then
1625
- stdbuf -e 0 -o 0 python3 "$SCRIPT_DIR/.omniopt.py" $args_string
1626
- EXIT_CODE=$?
1627
- else
1646
+ if [[ -n $RUN_WITH_PYSPY ]]; then
1628
1647
  echo "Starting OmniOpt with Py-Spy"
1629
1648
  pip install py-spy
1630
1649
  stdbuf -e 0 -o 0 py-spy record --rate 10 --subprocesses --native --output "$RUN_UUID.svg" python3 -- "$SCRIPT_DIR/.omniopt.py" $args_string
1631
1650
  EXIT_CODE=$?
1651
+ elif [[ -n $RUN_WITH_MEMRAY ]]; then
1652
+ echo "Starting OmniOpt with MemRay."
1653
+ echo "Check later on with 'memray flamegraph $RUN_UUID.bin'"
1654
+ export PYTORCH_NO_CUDA_MEMORY_CACHING=1
1655
+ export PYTHONFAULTHANDLER=1
1656
+ pip install memray
1657
+ stdbuf -e 0 -o 0 memray run -o "$RUN_UUID.bin" -- "$SCRIPT_DIR/.omniopt.py" $args_string
1658
+ EXIT_CODE=$?
1659
+ else
1660
+ stdbuf -e 0 -o 0 python3 "$SCRIPT_DIR/.omniopt.py" $args_string
1661
+ EXIT_CODE=$?
1632
1662
  fi
1633
1663
  else
1634
1664
  echo "Using coverage run -p because \$RUN_WITH_COVERAGE is set"
@@ -1636,6 +1666,10 @@ EOF
1636
1666
  EXIT_CODE=$?
1637
1667
  fi
1638
1668
 
1669
+ if [[ $live_share -eq 1 ]] && [[ -n $live_share_pid ]]; then
1670
+ kill -9 $live_share_pid >/dev/null 2>/dev/null
1671
+ fi
1672
+
1639
1673
  set -e
1640
1674
  trap 'calltracer' ERR
1641
1675
 
@@ -1843,7 +1877,7 @@ EOF
1843
1877
  kill_tail_when_squeue_job_empty "$started_job_nr" &
1844
1878
 
1845
1879
  tail_log_file() {
1846
- trap 'ask_cancel' SIGINT
1880
+ #trap 'ask_cancel' SIGINT
1847
1881
  # weird exec stuff for disabling the "Terminated" message coming from kill
1848
1882
  exec 3>&2 # 3 is now a copy of 2
1849
1883
  exec 2> /dev/null # 2 now points to /dev/null
@@ -1890,34 +1924,29 @@ EOF
1890
1924
  exit_code_lines=$(grep -i "exit-code:*" "$LOG_PATH" 2>/dev/null)
1891
1925
  exit_code_lines_lines=$?
1892
1926
  if [ $exit_code_lines_lines -ne 0 ] || [ -z "$exit_code_lines" ]; then
1893
- echo "WARN: grep failed or no exit-code line found."
1894
1927
  exit_code_lines=""
1895
1928
  fi
1896
1929
 
1897
1930
  exit_code_sed=$(echo "$exit_code_lines" | sed -e 's#Exit-Code:*[[:space:]]*##i' -e 's#,.*##')
1898
1931
  exit_code_sed_sed=$?
1899
1932
  if [ $exit_code_sed_sed -ne 0 ] || [ -z "$exit_code_sed" ]; then
1900
- echo "WARN: sed failed or no data after sed."
1901
1933
  exit_code_sed=""
1902
1934
  fi
1903
1935
 
1904
1936
  exit_code_tail=$(echo "$exit_code_sed" | tail -n1)
1905
1937
  exit_code_tail_tail=$?
1906
1938
  if [ $exit_code_tail_tail -ne 0 ] || [ -z "$exit_code_tail" ]; then
1907
- echo "WARN: tail failed or no data after tail."
1908
1939
  exit_code_tail=""
1909
1940
  fi
1910
1941
 
1911
- exit_code_only_digits=$(echo "$exit_code_tail" | grep -o '[0-9]\+')
1942
+ exit_code_only_digits=$(echo "$exit_code_tail" | grep -o '[0-9]\+' | tail -n1)
1912
1943
  if [ -z "$exit_code_only_digits" ]; then
1913
- echo "WARN: No valid exit code found, setting it to 3"
1914
1944
  exit_code_only_digits=3
1915
1945
  fi
1916
1946
 
1917
1947
  exit_code="$exit_code_only_digits"
1918
1948
 
1919
1949
  if ! [[ "$exit_code" =~ ^[0-9]+$ ]]; then
1920
- echo "WARN: exit_code invalid ('$exit_code'), setting to 3"
1921
1950
  exit_code=3
1922
1951
  fi
1923
1952
 
@@ -10,7 +10,6 @@ try:
10
10
  import difflib
11
11
  import logging
12
12
  import os
13
- import platform
14
13
  import re
15
14
  import traceback
16
15
  import numpy as np
@@ -227,12 +226,6 @@ def print_color(color: str, text: str) -> None:
227
226
  print(f"Error: {e}")
228
227
  print(text)
229
228
 
230
- def check_python_version() -> None:
231
- python_version = platform.python_version()
232
- supported_versions = ["3.8.10", "3.8.20", "3.9.21", "3.10.4", "3.10.12", "3.11.2", "3.11.9", "3.9.2", "3.11.3", "3.12.3", "3.12.4", "3.12.5", "3.12.6", "3.12.7", "3.12.7+", "3.12.8", "3.13.1", "3.13.2", "3.13.3", "3.13.5"]
233
- if python_version not in supported_versions:
234
- print_color("yellow", f"Warning: Supported python versions are {', '.join(supported_versions)}, but you are running {python_version}. This may or may not cause problems. Just is just a warning.")
235
-
236
229
  def create_widgets(_data: Any) -> Any:
237
230
  _plt, button, MAXIMUM_TEXTBOX, MINIMUM_TEXTBOX, _args, TEXTBOX_MINIMUM, TEXTBOX_MAXIMUM, update_graph = _data
238
231
 
@@ -882,5 +875,3 @@ def die_if_cannot_be_plotted(run_dir: Optional[str]) -> None:
882
875
  if not can_be_plotted(run_dir):
883
876
  log_error(f"{run_dir} contains multiple RESULTS and thus can only be plotted by parallel plot")
884
877
  sys.exit(2)
885
-
886
- check_python_version()