inter/misc/dynmet-search.js
2019-02-02 21:01:00 -08:00

98 lines
2.7 KiB
JavaScript

//
// Program that searches for optimal a,b,c values for dynamic metrics.
//
// Provide ideal tracking values for font sizes in idealTracking and start
// this program. It will run forever and print to stdout when it finds
// better a,b,c values that brings you closer to the ideal values.
//
// These are the initial a,b,c values. (Update if you find better values.)
let a = -0.02, b = 0.0755, c = -0.1021 // 0.00092
//
// These are the ideal tracking values.
let idealTracking = {
// 6: 0.05,
// 7: 0.04,
// 8: 0.03,
9: 0.01,
// 10: 0.015,
11: 0.005,
12: 0.0025,
13: 0,
// 14: 0,
// 15: -0.002,
16: -0.005,
// 17: -0.008,
18: -0.01,
// 20: -0.014,
// 24: -0.016,
// 30: -0.019,
40: -0.022,
}
let idealTrackingList = Object.keys(idealTracking).map(fontSize =>
[fontSize, idealTracking[fontSize]]
)
function sample(a, b, c) {
let idealDist = 0.0
for (let [fontSize, idealTracking] of idealTrackingList) {
let tracking = a + b * Math.pow(Math.E, c * fontSize)
let dist = Math.abs(tracking - idealTracking)
idealDist += dist
// console.log(`${fontSize} d=${tracking - idealTracking} d'=${dist}`)
}
// console.log(`idealDist=${idealDist}`)
return idealDist / idealTrackingList.length
}
const prec = 4 // precision
let bestConstants = { a, b, c }
let isneg = {
a: a < 0,
b: b < 0,
c: c < 0,
}
let bestDistance = sample(a, b, c)
console.log(
'------------------------------------------------------------------\n' +
`| Started at ${(new Date()).toLocaleString()} with initial values:\n` +
`| a = ${bestConstants.a}, b = ${bestConstants.b},` +
` c = ${bestConstants.c} // D ${bestDistance.toFixed(5)}\n` +
`| Ctrl-C to end.\n` +
'------------------------------------------------------------------'
)
function logNewBest() {
console.log(
`new best: a = ${a.toFixed(prec)}, b = ${b.toFixed(prec)}, c = ${c.toFixed(prec)} // D ${bestDistance.toFixed(5)}`
)
}
while (true) {
// a = parseFloat((bestConstants.a * ((Math.random() * 2.0) - 1.0)).toFixed(prec))
// b = parseFloat((bestConstants.b * ((Math.random() * 2.0) - 1.0)).toFixed(prec))
// c = parseFloat((bestConstants.c * ((Math.random() * 2.0) - 1.0)).toFixed(prec))
let a2 = bestConstants.a * ((Math.random() * 2.0) - 1.0)
let b2 = bestConstants.b * ((Math.random() * 2.0) - 1.0)
let c2 = bestConstants.c * ((Math.random() * 2.0) - 1.0)
if (isneg.a) { if (a2 > 0) { a2 = a } } else if (a2 < 0) { a2 = a }
if (isneg.b) { if (b2 > 0) { b2 = b } } else if (b2 < 0) { b2 = b }
if (isneg.c) { if (c2 > 0) { c2 = c } } else if (c2 < 0) { c2 = c }
a = a2
b = b2
c = c2
let dist = sample(a, b, c)
if (dist < bestDistance) {
bestDistance = dist
logNewBest()
}
}