Skip to content

Instantly share code, notes, and snippets.

@kdheepak
Last active August 17, 2023 04:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kdheepak/afc1ed987c19d67d738661559c2cc6b5 to your computer and use it in GitHub Desktop.
Save kdheepak/afc1ed987c19d67d738661559c2cc6b5 to your computer and use it in GitHub Desktop.
using Pkg
cd(mktempdir()) do
Pkg.activate(".")
Pkg.add(PackageSpec(name="JuMP", version="1.13.0"))
Pkg.add(PackageSpec(name="GLPK", version="1.1.2"),
preserve=PRESERVE_DIRECT)
Pkg.status()
end
using Test
using JuMP
using GLPK
function create_strength(a::Real, b::Real, c::Real, w::Real=1.0)
result = 0.0
result += max(0.0, min(1000.0, a * w)) * 1000000.0
result += max(0.0, min(1000.0, b * w)) * 1000.0
result += max(0.0, min(1000.0, c * w))
return result
end
const REQUIRED = create_strength(1000.0, 1000.0, 1000.0)
const STRONG = create_strength(1.0, 0.0, 0.0)
const MEDIUM = create_strength(0.0, 1.0, 0.0)
const WEAK = create_strength(0.0, 0.0, 1.0)
abstract type Constraint end
@kwdef struct Min <: Constraint
value::Int
end
@kwdef struct Max <: Constraint
value::Int
end
@kwdef struct HardMin <: Constraint
value::Int
end
@kwdef struct HardMax <: Constraint
value::Int
end
@kwdef struct Percent <: Constraint
value::Float64
end
@kwdef struct Fixed <: Constraint
value::Int
end
@kwdef struct Horizontal
constraints::Vector{Constraint}
end
@kwdef struct Vertical
constraints::Vector{Constraint}
end
struct Rect{T}
x::T
y::T
width::T
height::T
end
function split(layout, area; integer=true)
m = Model(GLPK.Optimizer)
N = length(layout.constraints)
total_length = layout isa Horizontal ? area.width : area.height
starting_position = layout isa Horizontal ? area.x : area.y
@variable(m, 0 <= lengths[1:N], integer = integer)
@variable(m, starting_position <= positions[1:N] <= starting_position + total_length, integer = integer)
@variable(m, ϵ_pos[1:N] >= 0)
@variable(m, ϵ_neg[1:N] >= 0)
@variable(m, δ_pos[1:N, 1:N] >= 0)
@variable(m, δ_neg[1:N, 1:N] >= 0)
for i in 1:N-1
@constraint m positions[i+1] == positions[i] + lengths[i]
end
@constraint m sum(lengths) == total_length
for i in 1:N
c = layout.constraints[i]
if c isa Min
@constraint m -1 * (lengths[i] - c.value) <= (ϵ_neg[i] / STRONG)
elseif c isa Max
@constraint m lengths[i] - c.value <= (ϵ_pos[i] / STRONG)
elseif c isa HardMin
@constraint m lengths[i] >= c.value
elseif c isa HardMax
@constraint m lengths[i] <= c.value
elseif c isa Fixed
@constraint m lengths[i] - c.value <= (ϵ_pos[i] / STRONG)
@constraint m -1 * (lengths[i] - c.value) <= (ϵ_neg[i] / STRONG)
elseif c isa Percent
@constraint m lengths[i] - (c.value * total_length / 100) <= (ϵ_pos[i] / STRONG)
@constraint m -1 * (lengths[i] - (c.value * total_length / 100)) <= (ϵ_neg[i] / STRONG)
end
end
for i in 1:N
for j in 1:N
if i != j
@constraint m lengths[i] - lengths[j] <= (δ_pos[i, j] / WEAK) * N
@constraint m -1 * (lengths[i] - lengths[j]) <= (δ_neg[i, j] / WEAK) * N
end
end
end
@objective(m, Min, sum(ϵ_pos) + sum(ϵ_neg) + sum(δ_neg) + sum(δ_pos))
# println(m)
optimize!(m)
# @show value.(ϵ_pos) value.(ϵ_neg)
# @show value.(δ_pos) value.(δ_neg)
[Rect{integer ? Int : Float64}(p, 0, l, 0) for (p, l) in zip(value.(positions), value.(lengths))]
end
function main(; kwargs...)
@testset "percents" begin
area = Rect(0, 0, 100, 1)
constraints = [Percent(33.3333), Percent(33.3333), Percent(33.3333)]
r1, r2, r3 = split(Horizontal(constraints), area; kwargs...)
@test r1.width == 34
@test r2.width == 33
@test r3.width == 33
end
@testset "min" begin
area = Rect(0, 0, 100, 1)
constraints = [Min(10), Min(10), Min(10)]
r1, r2, r3 = split(Horizontal(constraints), area; kwargs...)
@test r1.width == 34
@test r2.width == 33
@test r3.width == 33
area = Rect(0, 0, 100, 1)
constraints = [Percent(50), HardMin(10), Percent(50)]
r1, r2, r3 = split(Horizontal(constraints), area; kwargs...)
@test r1.width == 45
@test r2.width == 10
@test r3.width == 45
end
@testset "max" begin
area = Rect(0, 0, 100, 1)
constraints = [Max(10), Max(10), Max(10)]
r1, r2, r3 = split(Horizontal(constraints), area; kwargs...)
@test r1.width == 33
@test r2.width == 34
@test r3.width == 33
end
nothing
end
main(integer=true)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment