WUT_Computer_Science/Programming/WDWR/projekt/graph3.py
Krzysztof kuhy Rudnicki bd24dd57ea Hold the coursework to the same lint bar as the tooling
kuhy overruled the "do not fix coursework to be better than it was submitted"
rule: git history is the archive, so the working tree can be clean. This lands
the config and the mechanical half of the cleanup -- 9,281 ruff findings under
the fleet config down to 3,686, with no per-file-ignores anywhere.

What is in here:

- pyproject.toml, the first one in this repo. select = ["ALL"], mypy strict,
  and the vendored list mirrored into ruff exclude and coverage omit. Five
  rules are off and each says why; CPY001 is the only judgement call, because
  stamping a copyright header onto 137 university assignments would assert a
  licence that was never claimed. No hook is wired up yet -- a gate lands only
  once its subject is clean.

- ruff format + the safe fixes, then a second pass over the docstring rules
  ruff marks unsafe (they only edit docstring text). 108 files.

- TRAK/sightpy is vendored, not coursework: it is rafael-fuente/Python-Raytracer
  (BSD 3-Clause). Verified against a fresh upstream clone with line endings
  normalised -- 30 of 32 files byte-identical, ray.py and scene.py carrying a
  12- and 13-line local patch that counts rays for the report. 35 files that
  should never have been linted, now excluded and restored.

- WDWR, SPD, MOM and ECRYPT are fully clean, by hand and verified by running
  them: WDWR's three plot scripts print the same statistics as before, MOM's
  PuLP model solves to the same cost. WDWR's graph.py had a 342-character CSV
  header embedded as a string literal, which cannot be wrapped -- the data
  moved to data/pareto_front.csv. Two 0-byte .py stubs are deleted; an empty
  file is not a deliverable and git still has it.

Three harness bugs found by actually running things:

- `run` now forces MPLBACKEND=Agg. TRAK finished its ray trace in 37 seconds
  and then sat for 45 minutes: plt.show() had opened an image viewer and was
  waiting for someone to close the window.
- TRAK's main.py only pops that viewer with --show now, and its runner writes
  to a gitignored build/ via the new --entry-args. The default output path is
  outputs/output.png, which is TRACKED -- a plain run overwrote a submitted
  deliverable.
- course_lib.sh was 357 lines, over this repo's own cap. Split into
  course_probe.sh and course_run.sh.

Verified: ECOTE 26 tests pass, ECRYPT_PROJECT 99 pass, TRAK renders
cornell_box in 37s and exits 0, every module compiles, and every import ruff
removed was checked to be genuinely unused.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0172dj34FDpao6wsix8ZuCzE
2026-08-28 19:53:04 +02:00

166 lines
3.2 KiB
Python
Executable File

#!/usr/bin/env python3
"""Plot the inverse distribution of RISK for the three WDWR scenarios.
The companion of graph2.py: same three scenarios, same empirical cumulative
probability on the y axis, but the Gini risk measure on the x axis instead of
the profit.
"""
import logging
import matplotlib.pyplot as plt
import numpy as np
logger = logging.getLogger(__name__)
logging.basicConfig(format="%(message)s", level=logging.INFO)
# Sized for a report figure rather than for the screen.
LABEL_FONT_SIZE = 16
# Data for the three scenarios - Risk values
scenario1_risks = [
184.458,
195.09,
207.678,
278.26,
220.823,
181.042,
195.281,
199.255,
182.194,
181.295,
285.773,
185.306,
272.997,
288.405,
223.407,
213.341,
208.693,
354.01,
217.093,
301.892,
200.499,
637.424,
408.232,
308.314,
181.042,
470.693,
212.039,
184.694,
345.455,
205.291,
]
scenario2_risks = [
403.784,
414.043,
408.225,
664.379,
413.447,
448.303,
513.763,
439.966,
403.784,
408.366,
773.926,
459.531,
537.056,
795.835,
542.569,
512.817,
471.741,
879.425,
441.46,
533.521,
659.742,
990.73,
842.758,
776.278,
404.787,
989.35,
481.833,
409.978,
795.275,
421.261,
]
scenario3_risks = [
559.839,
576.633,
596.264,
942.092,
560.045,
679.026,
683.47,
627.607,
559.839,
562.478,
1245.41,
638.37,
675.366,
1132.8,
784.609,
686.634,
680.842,
1115.92,
572.793,
682.114,
914.647,
1211.67,
1051.95,
1104.87,
583.36,
1360.71,
743.425,
577.734,
1191.09,
581.791,
]
# Create figure with single plot
plt.figure(figsize=(12, 8))
# Sort the data for each scenario (descending order)
scenario1_sorted = sorted(scenario1_risks, reverse=True)
scenario2_sorted = sorted(scenario2_risks, reverse=True)
scenario3_sorted = sorted(scenario3_risks, reverse=True)
# Create y-axis values (cumulative distribution from 0 to 1)
num_points = len(scenario1_risks)
y_values = [i / num_points for i in range(1, num_points + 1)]
# Plot all three scenarios on the same graph
plt.plot(
scenario1_sorted, y_values, "b-o", label="Scenariusz 1", linewidth=2, markersize=4
)
plt.plot(
scenario2_sorted, y_values, "g-s", label="Scenariusz 2", linewidth=2, markersize=4
)
plt.plot(
scenario3_sorted, y_values, "r-^", label="Scenariusz 3", linewidth=2, markersize=4
)
# Add labels and title
plt.xlabel("Ryzyko", fontsize=LABEL_FONT_SIZE)
plt.ylabel("Odwrotna dystrybuanta", fontsize=LABEL_FONT_SIZE)
plt.xticks(fontsize=LABEL_FONT_SIZE)
plt.yticks(fontsize=LABEL_FONT_SIZE)
plt.ylim(0, 1) # Set y-axis limits to cut off values outside 0-1 range
plt.grid(visible=True, alpha=0.3)
plt.legend(fontsize=LABEL_FONT_SIZE)
# Format the plot
plt.tight_layout()
# Show the plot
plt.show()
# Print statistics for each scenario
logger.info("Scenario Statistics:")
for number, risks in enumerate(
(scenario1_risks, scenario2_risks, scenario3_risks), start=1
):
logger.info(
"Scenario %d - Mean: %.2f, Std: %.2f", number, np.mean(risks), np.std(risks)
)