I would like to know if and how the problem discussed Here can be solved using JuMP’s “powerfull means”
This is the problem of day 24 of the advent of code 2024.
You are asked to “fix” a 45-bit full-adder that has 4 pairs of inverted gates.
The idea that I would like to implement (if possible) is the following.
The final and intermediate gates are in the variable Zk. I build a matrix Az (length(zk), length(zk)) by setting the diagonal (initial configuration) =1.
I define the functions that are needed to test the full-adder.
I give as input a series of powers of two and return the square of the difference with respect to the exact result.
I expect that in some way the optimizer changes configuration (i.e. modifies the matrix Az, appropriately exchanging pairs of gates) looking for the min of my f().
Can it be done?
How?
function parseinp()
XY,Z=open("input_aoc24_d24.txt") do f
split(read(f, String), "\n\n")
end
XY=split.(split(XY, "\n"),": ")
Z=split.(split(Z, "\n")," -> ")
Z, XY
end
function mapkeyval(kz1,D,Z)
prl(a,op,b)= op=="OR" ? a||b : op=="AND" ? a && b : xor(a, b)
v=split.(first.(Z)," ")
k=last.(Z)
ikz=findfirst(==(kz1),k)
l,op,r = v[ikz]
if l in keys(D) && r in keys(D)
D[kz1]=prl(D[l],op,D[r])
elseif l in keys(D)
ir=findfirst(==(r),k)
D[kz1]=prl(D[l],op,mapkeyval(k[ir],D,Z))
elseif r in keys(D)
il=findfirst(==(l),k)
D[kz1]=prl(mapkeyval(k[il],D,Z),op,D[r])
else
ir=findfirst(==(r),k)
il=findfirst(==(l),k)
D[kz1]=prl(mapkeyval(k[il],D,Z),op,mapkeyval(k[ir],D,Z))
end
end
function swapz(Z,x,y)
Z[x][2],Z[y][2]=Z[y][2],Z[x][2]
end
function f(Az,Z,kz,kxy,kx,ky)
for i in eachindex(Zk)
for j in i:length(Zk)
Az[Zk[i],Zk[j]]==1 && swapz(Z,i,j)
end
end
mq=0
for n in eachindex(kxy)
D=Dict{String,Bool}()
for key in kxy
D[key]=false
end
for (i,d) in enumerate(digits(n, base=2))
D[kx[i]]=d==1
D[ky[i]]=d==1
end
mq+=(2n-reduce((s,c)->s*2+c, mapkeyval(j,D,Z) for j in kz ;init=0))^2
end
mq
end
#########################
Z, XY=parseinp()
kz=sort(filter(e->startswith(e,"z"),Zk),rev=true)
kxy=first.(XY)
kx=[x for x in kxy if startswith(x,"x")]
ky=[x for x in kxy if startswith(x,"y")]
Zk=String.(last.(Z))
Az0=fill(false,length(Zk),length(Zk))
for i in eachindex(Zk)
Az0[i,i] = true
end
d0=Dict{Tuple{String,String},Bool}()
for I in CartesianIndices(Az0)
d0[(Zk[I[1]],Zk[I[2]])]=Az0[I[1],I[2]]
end
using JuMP
@variable(MFA, Az[i = Zk,j = Zk],Bin,start = d0[i,j])
@constraint(MFA, c[i=Zk], sum(Az[i,j] for j in Zk) == 1)
#objective(MFA, Min, f)
here you can download the file to do some tests