| """Preference-conditioned metrics and utilities for two-property PolyEdit.""" |
| from __future__ import annotations |
|
|
| import numpy as np |
|
|
|
|
| def preference_grid(n=11): |
| return tuple((float(a), float(1.0 - a)) for a in np.linspace(0.0, 1.0, n)) |
|
|
|
|
| def reward_vector(poly, directions, values, means, scales, clip=3.0): |
| raw = [d * (values[poly][p] - means[p]) / (scales[p] + 1e-9) |
| for p, d in zip(("Egc", "Egb"), directions)] |
| return (np.clip(raw, -clip, clip) + clip) / (2.0 * clip) |
|
|
|
|
| def hypervolume_2d(points, reference=(0.0, 0.0)): |
| """Area dominated by two-dimensional maximization points above a fixed reference.""" |
| rx, ry = reference |
| pts = sorted(((max(float(x), rx), max(float(y), ry)) for x, y in points), reverse=True) |
| area, top = 0.0, ry |
| for x, y in pts: |
| if y > top: |
| area += (x - rx) * (y - top) |
| top = y |
| return area |
|
|
|
|
| def mip(weights, rewards): |
| return float(np.mean([np.dot(w, r) for w, r in zip(weights, rewards)])) |
|
|
|
|
| def induced_graph(graph, nodes): |
| nodes = set(nodes) |
| return {p: [q for q in graph.get(p, ()) if q in nodes] |
| for p in sorted(nodes) if any(q in nodes for q in graph.get(p, ())) } |
|
|