Initial release
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
-- beta57.lua: Beta(0.5, 0.7) distribution scheduler
|
||||
-- Requires beta_math companion for the inverse CDF computation.
|
||||
|
||||
local beta_math = require("beta_math")
|
||||
|
||||
scheduler = {
|
||||
name = "beta57",
|
||||
display = "Beta 57",
|
||||
description = "Beta(0.5,0.7) — smooth S-curve from RES4LYF",
|
||||
}
|
||||
|
||||
function schedule(output, num_steps, shift)
|
||||
local alpha = 0.5
|
||||
local beta = 0.7
|
||||
|
||||
for i = 0, num_steps - 1 do
|
||||
local u = (i + 0.5) / num_steps
|
||||
local t = 1.0 - beta_math.ppf(u, alpha, beta)
|
||||
output[i] = t
|
||||
end
|
||||
-- Sort descending
|
||||
local vals = {}
|
||||
for i = 0, num_steps - 1 do vals[i+1] = output[i] end
|
||||
table.sort(vals, function(a,b) return a > b end)
|
||||
for i = 0, num_steps - 1 do output[i] = vals[i+1] end
|
||||
clamp(output, num_steps)
|
||||
apply_shift(output, num_steps, shift)
|
||||
end
|
||||
|
||||
function apply_shift(ts, n, shift)
|
||||
if shift == 1.0 then return end
|
||||
for i = 0, n - 1 do
|
||||
local t = ts[i]; ts[i] = shift * t / (1.0 + (shift - 1.0) * t)
|
||||
end
|
||||
end
|
||||
|
||||
function clamp(ts, n)
|
||||
for i = 0, n - 1 do
|
||||
if ts[i] < 1e-6 then ts[i] = 1e-6 end
|
||||
if ts[i] > 1.0 then ts[i] = 1.0 end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,114 @@
|
||||
-- beta_math.lua: Beta distribution math helpers (companion data file)
|
||||
-- Provides regularized incomplete beta function and its inverse (ppf).
|
||||
-- Ported from engine/src/schedulers/scheduler-implementations.h
|
||||
|
||||
local M = {}
|
||||
|
||||
-- Log-gamma (uses Lua's built-in math library)
|
||||
local function lgamma(x)
|
||||
-- Lanczos approximation for log-gamma
|
||||
if x <= 0 then return 0 end
|
||||
local g = 7
|
||||
local c = {
|
||||
0.99999999999980993,
|
||||
676.5203681218851,
|
||||
-1259.1392167224028,
|
||||
771.32342877765313,
|
||||
-176.61502916214059,
|
||||
12.507343278686905,
|
||||
-0.13857109526572012,
|
||||
9.9843695780195716e-6,
|
||||
1.5056327351493116e-7
|
||||
}
|
||||
if x < 0.5 then
|
||||
return math.log(math.pi / math.sin(math.pi * x)) - lgamma(1 - x)
|
||||
end
|
||||
x = x - 1
|
||||
local a = c[1]
|
||||
local t = x + g + 0.5
|
||||
for i = 2, #c do
|
||||
a = a + c[i] / (x + i - 1)
|
||||
end
|
||||
return 0.5 * math.log(2 * math.pi) + (x + 0.5) * math.log(t) - t + math.log(a)
|
||||
end
|
||||
|
||||
-- Log of beta function: B(a,b) = Gamma(a)*Gamma(b)/Gamma(a+b)
|
||||
local function lbeta(a, b)
|
||||
return lgamma(a) + lgamma(b) - lgamma(a + b)
|
||||
end
|
||||
|
||||
-- Regularized incomplete beta function via continued fraction (Lentz's method)
|
||||
local function betainc(a, b, x)
|
||||
if x <= 0 then return 0 end
|
||||
if x >= 1 then return 1 end
|
||||
|
||||
-- Use symmetry for convergence
|
||||
if x > (a + 1) / (a + b + 2) then
|
||||
return 1 - betainc(b, a, 1 - x)
|
||||
end
|
||||
|
||||
local ln_pre = a * math.log(x) + b * math.log(1 - x) - lbeta(a, b)
|
||||
local qab = a + b
|
||||
local qap = a + 1
|
||||
local qam = a - 1
|
||||
local c = 1
|
||||
local d = 1 - qab * x / qap
|
||||
if math.abs(d) < 1e-30 then d = 1e-30 end
|
||||
d = 1 / d
|
||||
local h = d
|
||||
|
||||
for m = 1, 200 do
|
||||
local m2 = 2 * m
|
||||
-- Even numerator
|
||||
local aa = m * (b - m) * x / ((qam + m2) * (a + m2))
|
||||
d = 1 + aa * d; if math.abs(d) < 1e-30 then d = 1e-30 end
|
||||
c = 1 + aa / c; if math.abs(c) < 1e-30 then c = 1e-30 end
|
||||
d = 1 / d; h = h * d * c
|
||||
|
||||
-- Odd numerator
|
||||
aa = -((a + m) * (qab + m) * x) / ((a + m2) * (qap + m2))
|
||||
d = 1 + aa * d; if math.abs(d) < 1e-30 then d = 1e-30 end
|
||||
c = 1 + aa / c; if math.abs(c) < 1e-30 then c = 1e-30 end
|
||||
d = 1 / d
|
||||
local del = d * c; h = h * del
|
||||
|
||||
if math.abs(del - 1) < 3e-14 then break end
|
||||
end
|
||||
|
||||
return math.exp(ln_pre) * h / a
|
||||
end
|
||||
|
||||
-- Beta PDF
|
||||
local function beta_pdf(x, a, b)
|
||||
if x <= 0 or x >= 1 then return 0 end
|
||||
return math.exp((a - 1) * math.log(x) + (b - 1) * math.log(1 - x) - lbeta(a, b))
|
||||
end
|
||||
|
||||
-- Inverse CDF (ppf) via Newton's method
|
||||
function M.ppf(p, a, b)
|
||||
if p <= 0 then return 0 end
|
||||
if p >= 1 then return 1 end
|
||||
|
||||
-- Initial guess
|
||||
local mu = a / (a + b)
|
||||
local var = a * b / ((a + b)^2 * (a + b + 1))
|
||||
local sigma = math.sqrt(var)
|
||||
local x = mu + sigma * (2 * p - 1)
|
||||
if x < 0.001 then x = 0.001 end
|
||||
if x > 0.999 then x = 0.999 end
|
||||
|
||||
-- Newton-Raphson
|
||||
for _ = 1, 50 do
|
||||
local F = betainc(a, b, x) - p
|
||||
local f = beta_pdf(x, a, b)
|
||||
if math.abs(f) < 1e-30 then break end
|
||||
local dx = -F / f
|
||||
x = x + dx
|
||||
if x < 1e-10 then x = 1e-10 end
|
||||
if x > 1 - 1e-10 then x = 1 - 1e-10 end
|
||||
if math.abs(dx) < 1e-12 then break end
|
||||
end
|
||||
return x
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -0,0 +1,38 @@
|
||||
-- bong_tangent.lua: Tangent-based scheduler, concentrates at high noise
|
||||
|
||||
scheduler = {
|
||||
name = "bong_tangent",
|
||||
display = "Tangent",
|
||||
description = "Front-loaded (structural focus)",
|
||||
}
|
||||
|
||||
function schedule(output, num_steps, shift)
|
||||
local scale = 1.5
|
||||
for i = 0, num_steps - 1 do
|
||||
local frac = (i + 0.5) / num_steps
|
||||
local angle = frac * math.pi / 2.0
|
||||
local tan_val = math.tan(angle)
|
||||
output[i] = 1.0 - (2.0 / math.pi) * math.atan(tan_val * scale)
|
||||
end
|
||||
-- Sort descending
|
||||
local vals = {}
|
||||
for i = 0, num_steps - 1 do vals[i+1] = output[i] end
|
||||
table.sort(vals, function(a,b) return a > b end)
|
||||
for i = 0, num_steps - 1 do output[i] = vals[i+1] end
|
||||
clamp(output, num_steps)
|
||||
apply_shift(output, num_steps, shift)
|
||||
end
|
||||
|
||||
function apply_shift(ts, n, shift)
|
||||
if shift == 1.0 then return end
|
||||
for i = 0, n - 1 do
|
||||
local t = ts[i]; ts[i] = shift * t / (1.0 + (shift - 1.0) * t)
|
||||
end
|
||||
end
|
||||
|
||||
function clamp(ts, n)
|
||||
for i = 0, n - 1 do
|
||||
if ts[i] < 1e-6 then ts[i] = 1e-6 end
|
||||
if ts[i] > 1.0 then ts[i] = 1.0 end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,31 @@
|
||||
-- cosine.lua: Cosine scheduler — half-cosine S-curve
|
||||
|
||||
scheduler = {
|
||||
name = "cosine",
|
||||
display = "Cosine",
|
||||
description = "Cosine annealing — balanced S-curve",
|
||||
}
|
||||
|
||||
function schedule(output, num_steps, shift)
|
||||
for i = 0, num_steps - 1 do
|
||||
local frac = i / num_steps
|
||||
output[i] = 0.5 * (1.0 + math.cos(math.pi * frac))
|
||||
end
|
||||
clamp(output, num_steps)
|
||||
apply_shift(output, num_steps, shift)
|
||||
end
|
||||
|
||||
function apply_shift(ts, n, shift)
|
||||
if shift == 1.0 then return end
|
||||
for i = 0, n - 1 do
|
||||
local t = ts[i]
|
||||
ts[i] = shift * t / (1.0 + (shift - 1.0) * t)
|
||||
end
|
||||
end
|
||||
|
||||
function clamp(ts, n)
|
||||
for i = 0, n - 1 do
|
||||
if ts[i] < 1e-6 then ts[i] = 1e-6 end
|
||||
if ts[i] > 1.0 then ts[i] = 1.0 end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
-- ddim_uniform.lua: DDIM Uniform — log-SNR uniform (S-shaped)
|
||||
|
||||
scheduler = {
|
||||
name = "ddim_uniform",
|
||||
display = "DDIM Uniform",
|
||||
description = "Log-SNR uniform (S-shaped)",
|
||||
}
|
||||
|
||||
function schedule(output, num_steps, shift)
|
||||
local t_max = 0.9986
|
||||
local t_min = 0.0014
|
||||
local logit_max = math.log(t_max / (1 - t_max))
|
||||
local logit_min = math.log(t_min / (1 - t_min))
|
||||
|
||||
for i = 0, num_steps - 1 do
|
||||
local frac = i / num_steps
|
||||
local logit_t = logit_max + (logit_min - logit_max) * frac
|
||||
output[i] = 1.0 / (1.0 + math.exp(-logit_t))
|
||||
end
|
||||
clamp(output, num_steps)
|
||||
apply_shift(output, num_steps, shift)
|
||||
end
|
||||
|
||||
function apply_shift(ts, n, shift)
|
||||
if shift == 1.0 then return end
|
||||
for i = 0, n - 1 do
|
||||
local t = ts[i]
|
||||
ts[i] = shift * t / (1.0 + (shift - 1.0) * t)
|
||||
end
|
||||
end
|
||||
|
||||
function clamp(ts, n)
|
||||
for i = 0, n - 1 do
|
||||
if ts[i] < 1e-6 then ts[i] = 1e-6 end
|
||||
if ts[i] > 1.0 then ts[i] = 1.0 end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,31 @@
|
||||
-- linear.lua: Linear (uniform) scheduler — the ACE-Step default
|
||||
|
||||
scheduler = {
|
||||
name = "linear",
|
||||
display = "Linear",
|
||||
description = "Uniform spacing (default)",
|
||||
}
|
||||
|
||||
function schedule(output, num_steps, shift)
|
||||
for i = 0, num_steps - 1 do
|
||||
output[i] = 1.0 - i / num_steps
|
||||
end
|
||||
apply_shift(output, num_steps, shift)
|
||||
end
|
||||
|
||||
-- Standard shift warp: t' = shift*t / (1 + (shift-1)*t)
|
||||
function apply_shift(ts, n, shift)
|
||||
if shift == 1.0 then return end
|
||||
for i = 0, n - 1 do
|
||||
local t = ts[i]
|
||||
ts[i] = shift * t / (1.0 + (shift - 1.0) * t)
|
||||
end
|
||||
end
|
||||
|
||||
-- Clamp to [1e-6, 1.0]
|
||||
function clamp(ts, n)
|
||||
for i = 0, n - 1 do
|
||||
if ts[i] < 1e-6 then ts[i] = 1e-6 end
|
||||
if ts[i] > 1.0 then ts[i] = 1.0 end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,38 @@
|
||||
-- linear_quadratic.lua: Linear start, quadratic finish
|
||||
|
||||
scheduler = {
|
||||
name = "linear_quadratic",
|
||||
display = "Linear-Quadratic",
|
||||
description = "Linear start, quadratic finish",
|
||||
}
|
||||
|
||||
function schedule(output, num_steps, shift)
|
||||
local crossover = 0.5
|
||||
local n_linear = math.max(math.floor(num_steps * crossover), 1)
|
||||
local n_quad = num_steps - n_linear
|
||||
local t_cross = 1.0 - crossover
|
||||
|
||||
for i = 0, n_linear - 1 do
|
||||
output[i] = 1.0 - i * crossover / n_linear
|
||||
end
|
||||
for i = 0, n_quad - 1 do
|
||||
local frac = (i + 1) / n_quad
|
||||
output[n_linear + i] = t_cross * (1.0 - frac * frac)
|
||||
end
|
||||
clamp(output, num_steps)
|
||||
apply_shift(output, num_steps, shift)
|
||||
end
|
||||
|
||||
function apply_shift(ts, n, shift)
|
||||
if shift == 1.0 then return end
|
||||
for i = 0, n - 1 do
|
||||
local t = ts[i]; ts[i] = shift * t / (1.0 + (shift - 1.0) * t)
|
||||
end
|
||||
end
|
||||
|
||||
function clamp(ts, n)
|
||||
for i = 0, n - 1 do
|
||||
if ts[i] < 1e-6 then ts[i] = 1e-6 end
|
||||
if ts[i] > 1.0 then ts[i] = 1.0 end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,36 @@
|
||||
-- power.lua: Power-law scheduler with configurable exponent
|
||||
|
||||
scheduler = {
|
||||
name = "power",
|
||||
display = "Power (p=2)",
|
||||
description = "Power-law t^p, front-loaded",
|
||||
params = {
|
||||
{ key = "exponent", type = "slider", label = "Exponent",
|
||||
default = 2.0, min = 0.5, max = 5.0, step = 0.1,
|
||||
hint = "Higher values front-load more steps at high noise" },
|
||||
},
|
||||
}
|
||||
|
||||
function schedule(output, num_steps, shift)
|
||||
local p = (params and params.exponent) or 2.0
|
||||
for i = 0, num_steps - 1 do
|
||||
local frac = i / num_steps
|
||||
output[i] = (1.0 - frac) ^ p
|
||||
end
|
||||
clamp(output, num_steps)
|
||||
apply_shift(output, num_steps, shift)
|
||||
end
|
||||
|
||||
function apply_shift(ts, n, shift)
|
||||
if shift == 1.0 then return end
|
||||
for i = 0, n - 1 do
|
||||
local t = ts[i]; ts[i] = shift * t / (1.0 + (shift - 1.0) * t)
|
||||
end
|
||||
end
|
||||
|
||||
function clamp(ts, n)
|
||||
for i = 0, n - 1 do
|
||||
if ts[i] < 1e-6 then ts[i] = 1e-6 end
|
||||
if ts[i] > 1.0 then ts[i] = 1.0 end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,41 @@
|
||||
-- sgm_uniform.lua: SGM Uniform (Karras) — uniform in σ^(1/ρ) space
|
||||
|
||||
scheduler = {
|
||||
name = "sgm_uniform",
|
||||
display = "SGM-Uniform (Karras)",
|
||||
description = "Karras σ-ramp (ρ=7), front-loads structural steps",
|
||||
}
|
||||
|
||||
function schedule(output, num_steps, shift)
|
||||
local t_max = 0.999
|
||||
local t_min = 0.001
|
||||
local sigma_max = t_max / (1 - t_max)
|
||||
local sigma_min = t_min / (1 - t_min)
|
||||
local rho = 7.0
|
||||
|
||||
local inv_rho = 1.0 / rho
|
||||
local s_max = sigma_max ^ inv_rho
|
||||
local s_min = sigma_min ^ inv_rho
|
||||
|
||||
for i = 0, num_steps - 1 do
|
||||
local frac = i / num_steps
|
||||
local sigma = (s_max + frac * (s_min - s_max)) ^ rho
|
||||
output[i] = sigma / (1 + sigma)
|
||||
end
|
||||
clamp(output, num_steps)
|
||||
apply_shift(output, num_steps, shift)
|
||||
end
|
||||
|
||||
function apply_shift(ts, n, shift)
|
||||
if shift == 1.0 then return end
|
||||
for i = 0, n - 1 do
|
||||
local t = ts[i]; ts[i] = shift * t / (1.0 + (shift - 1.0) * t)
|
||||
end
|
||||
end
|
||||
|
||||
function clamp(ts, n)
|
||||
for i = 0, n - 1 do
|
||||
if ts[i] < 1e-6 then ts[i] = 1e-6 end
|
||||
if ts[i] > 1.0 then ts[i] = 1.0 end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user