| Code: | function wires = solver(B)
Bsize = size(B);
% wires = zeros(ceil((Bsize(1)+Bsize(2))/2), 4);
wires = zeros( ((Bsize(1)-1) * Bsize(2)) + (Bsize(1) * (Bsize(2)-1)), 4);
nwires = 0;
pValues = unique(B(B>0))';
nPins = size(pValues, 2);
pCounts = zeros(size(pValues));
for j = 1:nPins
pCounts(j) = nnz(B == pValues(j));
end
%% skip single pins
skip = pCounts == 1;
if any(skip)
nPins = nPins - sum(skip);
% skippins = pValues(skip);
% nskippins = sum(skip);
% for j = 1:nskippins
% B(B==skippins(j)) = -1;
% end
pValues = pValues(~skip);
pCounts = pCounts(~skip);
end
%% create distance and connection matrices and add simple wires
pDistances = cell(1, nPins);
pTriDistances = cell(1, nPins);
pDistancesX = pDistances;
pDistancesY = pDistances;
pConnected = pDistances;
pXvs = pDistances;
pYvs = pDistances;
for pix = 1:nPins
[pXvs{pix} pYvs{pix}] = find(B == pValues(pix));
pConnected{pix} = false(pCounts(pix));
pDistancesX{pix} = bsxfun(@(x1, x2) abs(x1-x2), pXvs{pix}, pXvs{pix}');
pDistancesY{pix} = bsxfun(@(y1, y2) abs(y1-y2), pYvs{pix}, pYvs{pix}');
pDistances{pix} = pDistancesX{pix} + pDistancesY{pix};
pTriDistances{pix} = triu(pDistances{pix});
% add wires for adjacent pins immediately
adjacent = pTriDistances{pix} == 1;
if any(any(adjacent))
[aix1 aix2] = find(adjacent);
nadjacent = length(aix1);
for j = 1:nadjacent
pConnected{pix}(aix1(j), aix2(j)) = true;
pConnected{pix}(aix2(j), aix1(j)) = true;
% disp(['adjacent: <' num2str([pXvs{pix}(aix1(aix)) pYvs{pix}(aix1(aix)) pXvs{pix}(aix2(aix)) pYvs{pix}(aix2(aix))]) '> ?']);
end
[wires nwires] = addwires(wires, nwires, [pXvs{pix}(aix1) pYvs{pix}(aix1) pXvs{pix}(aix2) pYvs{pix}(aix2)]);
end
end
%% check for wires of length 2
[sv svix] = sort(pValues, 'descend');
for cix = 1:nPins
pix = svix(cix);
d2b = pTriDistances{pix} == 2;
if any(any(d2b))
d2bstraight = d2b & pDistancesX{pix} ~= 1;
d2bcorner = d2b & ~d2bstraight;
if any(any(d2bstraight))
[ix1 ix2] = find(d2bstraight);
pins = [pXvs{pix}(ix1) pYvs{pix}(ix1) pXvs{pix}(ix2) pYvs{pix}(ix2)];
midpoints = (pins(:, [1, 2]) + pins(:, [3, 4])) / 2;
midpointsfree = pointsfree(B, midpoints);
% midpointsfree = false(size(midpoints, 1), 1);
% for j = 1:size(midpoints, 1);
% if ~B(midpoints(j, 1), midpoints(j, 2))
% midpointsfree(j) = true;
% pConnected{pix}(ix1(j), ix2(j)) = true;
% pConnected{pix}(ix2(j), ix1(j)) = true;
% end
% end
if any(midpointsfree)
pins = pins(midpointsfree, :);
midpoints = midpoints(midpointsfree, :);
for j = 1:size(midpoints, 1)
pConnected{pix}(ix1(j), ix2(j)) = true;
pConnected{pix}(ix2(j), ix1(j)) = true;
end
[wires nwires] = addwires(wires, nwires, [ ...
pins(:, [1, 2]) midpoints; ...
pins(:, [3, 4]) midpoints]);
end
end
if any(any(d2bcorner))
[ix1 ix2] = find(d2bcorner);
pins = [pXvs{pix}(ix1) pYvs{pix}(ix1) pXvs{pix}(ix2) pYvs{pix}(ix2)];
n = size(ix1, 1);
midpoints = [pins(:, 1) pins(:, 4); pins(:, 3) pins(:, 2)];
midpointsfree = pointsfree(B, midpoints);
for j = 1:n
pick = false;
if midpointsfree(j)
freemidpoint = midpoints(j, :);
pick = true;
elseif midpointsfree(j+n)
freemidpoint = midpoints(j+n, :);
pick = true;
end
if pick
[wires nwires] = addwires(wires, nwires, [ ...
pins(j, [1, 2]) freemidpoint; ...
pins(j, [3, 4]) freemidpoint]);
end
end
end
end
end
% pConnected{pix} = convexconnections(pConnected{pix});
%% find high-values
% % pPotential = pValues .* pCounts;
% pPotential = pValues;
%
% [mp mpix] = sort(pPotential, 'descend');
%
% for cix = 1:nPins
% pix = mpix(cix);
%
% connected = pConnected{pix};
% distances = pDistances{pix};
% distancesX = pDistancesX{pix};
% distancesY = pDistancesY{pix};
% xvs = pXvs{pix};
% yvs = pYvs{pix};
%
%
%
%
% end
wires = wires(1:nwires, :);
% wires = zeros(0, 4);
end
function ret = pointsfree(B, points)
ret = false(size(points, 1), 1);
for j = 1:size(points, 1);
if ~B(points(j, 1), points(j, 2))
ret(j) = true;
end
end
end
function [wires nwires] = addwires(wires, nwires, newwires)
nnewwires = size(newwires, 1);
wires(nwires+1:nwires+nnewwires, :) = newwires;
nwires = nwires + nnewwires;
end
function connected = convexconnections(connected)
if ~any(any(connected)) return; end
nc = nnz(connected);
while true
connected = connected + connected ^ 2;
newnc = nnz(connected);
if nc ~= newnc nc = newnc;
else break;
end
end
connected = ~(~connected | eye(size(connected)));
end
function d = d(x1, y1, x2, y2)
d=sum(abs([x1-y1,x2-y2]));
end
|