Last active
August 17, 2023 04:51
-
-
Save kdheepak/afc1ed987c19d67d738661559c2cc6b5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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