Spaces:
Sleeping
Sleeping
Update data_gen.py
Browse files- data_gen.py +37 -63
data_gen.py
CHANGED
|
@@ -1,80 +1,54 @@
|
|
| 1 |
"""
|
| 2 |
data_gen.py
|
| 3 |
-
|
| 4 |
-
Scalar mesh test data. Each sample is (a, b, c) — all single floats.
|
| 5 |
-
|
| 6 |
-
A ∈ [0.1, 0.9] — constraint scalar (top input)
|
| 7 |
-
B ∈ [0.1, 0.9] — objective scalar (bottom input)
|
| 8 |
-
C — feasibility center (what the mesh must learn to produce)
|
| 9 |
-
|
| 10 |
-
All C values kept in [0.1, 0.9] so the scalar Hooke mesh can represent them
|
| 11 |
-
without needing to amplify beyond the input range.
|
| 12 |
-
|
| 13 |
-
SEEN during training : heavy_a | avg | diff
|
| 14 |
-
OOD (test only) : heavy_b
|
| 15 |
-
|
| 16 |
-
If the mesh generalises:
|
| 17 |
-
It learned "weighted combination of A and B" as a concept
|
| 18 |
-
→ it applies unseen weighting (B-heavy) without training on it.
|
| 19 |
"""
|
|
|
|
|
|
|
| 20 |
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
SAMPLES_PER_TYPE = 2500 # × 4 types = 10 000 total
|
| 24 |
|
| 25 |
-
|
| 26 |
-
# name : (lambda, seen?)
|
| 27 |
-
'heavy_a': (lambda a, b: 0.8*a + 0.2*b, True),
|
| 28 |
-
'avg': (lambda a, b: 0.5*a + 0.5*b, True),
|
| 29 |
-
'diff': (lambda a, b: 0.5 + 0.4*(a - b), True), # signed diff, offset to [0.1,0.9]
|
| 30 |
-
'heavy_b': (lambda a, b: 0.2*a + 0.8*b, False), # OOD
|
| 31 |
-
}
|
| 32 |
-
|
| 33 |
-
def generate(n_per=SAMPLES_PER_TYPE, seed=42):
|
| 34 |
rng = np.random.default_rng(seed)
|
| 35 |
data = []
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
random.shuffle(data)
|
| 44 |
return data
|
| 45 |
|
|
|
|
|
|
|
|
|
|
| 46 |
if __name__ == '__main__':
|
| 47 |
parser = argparse.ArgumentParser()
|
| 48 |
-
parser.add_argument('--
|
| 49 |
-
parser.add_argument('--
|
| 50 |
args = parser.parse_args()
|
| 51 |
|
| 52 |
-
data = generate(args.n)
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
split = int(len(seen) * 0.9)
|
| 59 |
-
train = seen[:split]
|
| 60 |
-
test = seen[split:] + ood
|
| 61 |
-
|
| 62 |
-
random.shuffle(test)
|
| 63 |
-
|
| 64 |
-
out = pathlib.Path(args.out)
|
| 65 |
out.mkdir(exist_ok=True)
|
| 66 |
with open(out/'train.json','w') as f: json.dump(train, f)
|
| 67 |
with open(out/'test.json', 'w') as f: json.dump(test, f)
|
| 68 |
-
|
| 69 |
-
from collections import Counter
|
| 70 |
-
tr = Counter(d['type'] for d in train)
|
| 71 |
-
te = Counter(d['type'] for d in test)
|
| 72 |
-
|
| 73 |
-
print(f"\n{'─'*50}")
|
| 74 |
-
print(f" {'Type':<12} {'Train':>7} {'Test':>7} Split")
|
| 75 |
-
print(f" {'─'*12} {'─'*7} {'─'*7} {'─'*8}")
|
| 76 |
-
for t, (fn, seen_flag) in DATASETS.items():
|
| 77 |
-
label = 'SEEN' if seen_flag else 'OOD ✗'
|
| 78 |
-
print(f" {t:<12} {tr.get(t,0):>7} {te.get(t,0):>7} {label}")
|
| 79 |
-
print(f"\n Train total: {len(train)} Test total: {len(test)}")
|
| 80 |
-
print(f" Saved → {out}/train.json {out}/test.json\n")
|
|
|
|
| 1 |
"""
|
| 2 |
data_gen.py
|
| 3 |
+
N-Dimensional Vector Data for the Triangulated Mesh.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
"""
|
| 5 |
+
import numpy as np
|
| 6 |
+
import json, pathlib, random, argparse
|
| 7 |
|
| 8 |
+
DIM = 8 # N dimensions = N nodes at A, B, and C
|
| 9 |
+
SAMPLES_PER_TYPE = 1000
|
|
|
|
| 10 |
|
| 11 |
+
def generate(n_per=SAMPLES_PER_TYPE, dim=DIM, seed=42):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
rng = np.random.default_rng(seed)
|
| 13 |
data = []
|
| 14 |
+
|
| 15 |
+
# We will train the mesh to physically wire three different logic gates:
|
| 16 |
+
for _ in range(n_per):
|
| 17 |
+
a = rng.uniform(0.1, 0.9, dim)
|
| 18 |
+
b = rng.uniform(0.1, 0.9, dim)
|
| 19 |
+
|
| 20 |
+
# 1. Direct blending (Straight down)
|
| 21 |
+
c_blend = 0.7 * a + 0.3 * b
|
| 22 |
+
data.append({'a': round_list(a), 'b': round_list(b), 'c': round_list(c_blend), 'type': 'blend'})
|
| 23 |
+
|
| 24 |
+
# 2. Subtraction logic
|
| 25 |
+
c_diff = 0.5 + 0.4 * (a - b)
|
| 26 |
+
data.append({'a': round_list(a), 'b': round_list(b), 'c': round_list(c_diff), 'type': 'diff'})
|
| 27 |
+
|
| 28 |
+
# 3. Lateral Routing (A rolls right by 1, B rolls left by 1)
|
| 29 |
+
# This forces the mesh to use its diagonal triangulated springs!
|
| 30 |
+
c_route = 0.5 * np.roll(a, 1) + 0.5 * np.roll(b, -1)
|
| 31 |
+
data.append({'a': round_list(a), 'b': round_list(b), 'c': round_list(c_route), 'type': 'route'})
|
| 32 |
+
|
| 33 |
random.shuffle(data)
|
| 34 |
return data
|
| 35 |
|
| 36 |
+
def round_list(arr):
|
| 37 |
+
return [round(float(x), 4) for x in arr]
|
| 38 |
+
|
| 39 |
if __name__ == '__main__':
|
| 40 |
parser = argparse.ArgumentParser()
|
| 41 |
+
parser.add_argument('--dim', type=int, default=DIM)
|
| 42 |
+
parser.add_argument('--n', type=int, default=SAMPLES_PER_TYPE)
|
| 43 |
args = parser.parse_args()
|
| 44 |
|
| 45 |
+
data = generate(args.n, args.dim)
|
| 46 |
+
|
| 47 |
+
split = int(len(data) * 0.9)
|
| 48 |
+
train, test = data[:split], data[split:]
|
| 49 |
+
|
| 50 |
+
out = pathlib.Path('data')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
out.mkdir(exist_ok=True)
|
| 52 |
with open(out/'train.json','w') as f: json.dump(train, f)
|
| 53 |
with open(out/'test.json', 'w') as f: json.dump(test, f)
|
| 54 |
+
print(f"Generated {len(data)} samples (Dim={args.dim}). Saved to data/train.json and data/test.json")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|