Extended find of unique tuples in a relation represented by a BDD - algorithm

Consider {<1,2>, <1,3>, <1,7>, <0,4>} as the set of tuples of a relation R. Now consider that R is represented (via its membership function) by a BDD. That is, The BDD representing R depends on variables {x1,x2, y1, y2, y3} where {x1, x2} are used to represent the first element of every tuple and {y1, y2, y3} are used to represent the second element.
Now, consider the problem of finding the set of tuples that have unique values in its first element. For the relation above that set would be {<0,4>}. All the other elements are discarded as they are more than one value having 1 in the first component.
As a second example consider the relation with set of tuples {<1,2>, <1,3>, <1,7>, <2,3>, <2,5>, <0,4>}. In such a case the expected result is still {<0,4>} as 2 appears more than once as first element.
The problem can be also seen as abstracting away the variables {y1,y2,y3} such that only unique values for {x1,x2} remain. With this result, the expected relation can be reconstructed by computing the conjunction of the resulting BDD with the input one.
In summary, the the question is: which are the BDD operations that have to be performed on The representation of R to obtain the BDD with only the unique tuples.
Notice that this is a genralization of this question
EDIT 1:
The following code reflects the implementation I have so far. However, I am wondering if it is possible to get a more efficient version. For simplicity I intentionally omit the handling of the computed table (crucial to get better time complexity). Additionally, I use &, | and ! to denote the conjunction, disjunction and complement operations on BDDs.
BDD uniqueAbstract(BDD f, BDD cube) {
if ((f.IsZero() || f.IsOne()) && !cube.IsOne())
return zero();
BDD T = high(f);
BDD E = low(f);
if(level(f) == level(c)) { // current var is abstracted
BDD uniqueThen = uniqueAbstract(T, high(c));
BDD existElse = existAbstract(E, high(c));
BDD existThen = existAbstract(T, high(c));
BDD uniqueElse = uniqueAbstract(E, high(c));
return (uniqueThen & !existElse) | (uniqueElse & !existThen)
} else {
BDD uniqueThen = uniqueAbstract(T,c);
BDD uniqueElse = uniqueAbstract(E,c);
return ite(top(f), uniqueThen, uniqueElse);
}
}
EDIT2: After trying three different implementations there are still some performance issues. Let me describe the three of them.
A C implementation of my approach, let me call it the reference implementation4.
The implementation proposed by user meolic in the accepted answer3.
A hybrid approach between the two and available2.
The goal of this update is to analyze a bit the results from using the three approaches. As time measures seem misleading at this time to judge them, I decided to evaluate the implementations on a different set of measures.
Recursive calls
Cache hits
Abstract simple. Number of times the function call was solved without requiring existential abstraction.
Abstract complex: Number of times the function call was solved requiring existential abstraction.
Exist abstract: Number of calls to the existential abstraction.
The results for implementation 1: (21123 ms):
Unique abstraction statistics:
Recursive calls: 1728549.000000
Cache hits: 638745.000000
Non abstract: 67207.000000
Abstract simple: 0.000000
Abstract complex: 0.000000
Exist abstract: 1593430.000000
Results for implementation 2: (run time: 54727 ms)
Unique abstraction statistics:
Recursive calls: 191585.000000
Cache hits: 26494.000000
Abstract simple: 59788.000000
Abstract complex: 12011.000000
Exist abstract: 24022.000000
Results for implementation 3: (run time: 20215 ms)
Unique abstraction statistics:
Recursive calls: 268044.000000
Cache hits: 30668.000000
Abstract simple: 78115.000000
Abstract complex: 46473.000000
Exist abstract: 92946.000000
EDIT 3: The following results were obtained after implementing every logical operation in terms of ITE5.
uniqueAbstractRecRef (21831 ms)
Unique abstraction statistics:
Total calls: 1723239
Optimized calls: 0
Total exist abstract calls: 30955618
Unique abstract calls to exist abstract: 2385915
Total ite calls: 3574555
Out of the total time, uniqueAbstractRecRef takes 4001 ms (12.4%)
uniqueAbstractSERec (56761 ms)
Unique abstraction statistics:
Total calls: 193627
Optimized calls: 60632
Total exist abstract calls: 16475806
Unique abstract calls to exist abstract: 24304
Total ite calls: 1271844
Out of the total time, uniqueAbstractSERec takes 33918 ms (51.5%)
uniqueAbstractRec (20587 ms)
Unique abstraction statistics:
Total calls: 270205
Optimized calls: 78486
Total exist abstract calls: 13186348
Unique abstract calls to exist abstract: 93060
Total ite calls: 1256872
Out of the total time, uniqueAbstractRec takes 3354 ms (10.6%)

There exist simple and efficient solution if variables are ordered in such a way that x1 and x2 are at the top of BDD.
Consider BDD for second example.
You can traverse (in breadth-first order) first two layers of it to get four sub-BDDs. One for each possible combination of x1,x2. Three of those sub-BDDs a rooted at y1 and fourth is empty (constant False).
Now you can count number of elements in each sub-BDD (Algorithm C from Knuth's Volume 4 Fascicle 1, Bitwise Tricks & Techniques; Binary Decision Diagrams).
If number of elements in sub-BDD is greater than 1 then drop it (shortcut from parent node directly to False), otherwise leave it as it is.
It is possible to run this algorithm in single pass by memoizing partial results while counting elements.

Here is my implementation. I have studied author's proposed solution and it seems to me that it is the best if not the only simple BDD-based solution for arbitrary ordering. However, there may be some improvements if the algorithm is implemented in my way- PLEASE CHECK. I am using my own wrapper over BDD package but you should not have any troubles to understand it.
EDITED: I have simplified the solution, function Bdd_GetVariableChar() is not used anymore.
/* TESTING SOLUTION FOR QUESTION ON STACK OVERFLOW */
/* bdd_termFalse,bdd_termTrue: Boolean constants */
/* Bdd_isTerminal(f): check if f is Boolean constant */
/* Bdd_Low(f),Bdd_High(f): 'else' and 'then' subfunction */
/* Bdd_Top(f): literal function representing topvar of f */
/* Bdd_IsSmaller(f,g): check if topvar of f is above topvar of g */
/* existentialAbstraction(f,cube): \exist v.f for all v in cube */
Bdd_Edge specialAbstraction(Bdd_Edge f, Bdd_Edge cube) {
if (Bdd_isTerminal(cube)) return f;
if (Bdd_isTerminal(f)) return bdd_termFalse;
if (Bdd_IsSmaller(f,cube)) {
Bdd_Edge E,T;
E = specialAbstraction(Bdd_Low(f),cube);
T = specialAbstraction(Bdd_High(f),cube);
return Bdd_ITE(Bdd_Top(f),T,E);
} else if (Bdd_IsSmaller(cube,f)) {
return bdd_termFalse;
} else {
Bdd_Edge E,T;
cube = Bdd_High(cube);
E = Bdd_Low(f);
T = Bdd_High(f);
if (Bdd_isEqv(E,bdd_termFalse)) {
return specialAbstraction(T,cube);
} else if (Bdd_isEqv(T,bdd_termFalse)) {
return specialAbstraction(E,cube);
} else {
Bdd_Edge EX,TX,R;
EX = existentialAbstraction(E,cube);
TX = existentialAbstraction(T,cube);
if (Bdd_isEqv(EX,TX)) return bdd_termFalse;
R = Bdd_ITE(Bdd_ITE(EX,bdd_termFalse,T),
bdd_termTrue,
Bdd_ITE(TX,bdd_termFalse,E));
return specialAbstraction(R,cube);
}
}
}
And, yes, if variable ordering is fixed with x above y, the algorithm can really be much more efficient - you can remove all the calculations from the most complex 'else' block and just return 0.
Here are some testing runs:
CUBE (JUST IN CASE YOU ARE NOT FAMILIAR WITH BDD ALGORITHMS)
+ y1 y2 y3 y4 y5
ORIGINAL (ORDERED WITH X ABOVE Y)
+ *x1 *x2 x3 *x4 x5 y1 *y2 y3 y4 y5
+ *x1 x2 *x3 *x4 *x5 y1 y2 *y3 y4 y5
+ *x1 x2 *x3 *x4 x5 *y1 y2 *y3 y4 y5
+ *x1 x2 *x3 x4 *x5 y1 *y2 y3 *y4 *y5
+ *x1 x2 x3 *x4 x5 *y1 *y2 *y3 *y4 y5
+ *x1 x2 x3 *x4 x5 *y1 y2 y3 *y4 *y5
+ x1 *x2 *x3 *x4 *x5 y1 y2 y3 y4 *y5
+ x1 x2 *x3 x4 x5 *y1 *y2 *y4 *y5
+ x1 x2 x3 *x4 *x5 *y1 *y2 *y3 y4 *y5
ABSTRACTION
+ *x1 *x2 x3 *x4 x5
+ *x1 x2 *x3 *x4
+ *x1 x2 *x3 x4 *x5
+ x1 *x2 *x3 *x4 *x5
+ x1 x2 x3 *x4 *x5
ORIGINAL (ORDERED WITH Y ABOVE X)
+ *y1 *y2 *y3 *y4 *y5 x1 x2 *x3 x4 x5
+ *y1 *y2 *y3 *y4 y5 *x1 x2 x3 *x4 x5
+ *y1 *y2 *y3 y4 *y5 x1 x2 x3 *x4 *x5
+ *y1 *y2 y3 *y4 *y5 x1 x2 *x3 x4 x5
+ *y1 y2 *y3 y4 y5 *x1 x2 *x3 *x4 x5
+ *y1 y2 y3 *y4 *y5 *x1 x2 x3 *x4 x5
+ y1 *y2 y3 *y4 *y5 *x1 x2 *x3 x4 *x5
+ y1 *y2 y3 y4 y5 *x1 *x2 x3 *x4 x5
+ y1 y2 *y3 y4 y5 *x1 x2 *x3 *x4 *x5
+ y1 y2 y3 y4 *y5 x1 *x2 *x3 *x4 *x5
ABSTRACTION
+ *x1 *x2 x3 *x4 x5
+ *x1 x2 *x3 *x4
+ *x1 x2 *x3 x4 *x5
+ x1 *x2 *x3 *x4 *x5
+ x1 x2 x3 *x4 *x5
ORIGINAL (MIXED ORDER)
+ *x1 *x2 y1 *y2 y3 y4 y5 x3 *x4 x5
+ *x1 x2 *y1 *y2 *y3 *y4 y5 x3 *x4 x5
+ *x1 x2 *y1 y2 *y3 y4 y5 *x3 *x4 x5
+ *x1 x2 *y1 y2 y3 *y4 *y5 x3 *x4 x5
+ *x1 x2 y1 *y2 y3 *y4 *y5 *x3 x4 *x5
+ *x1 x2 y1 y2 *y3 y4 y5 *x3 *x4 *x5
+ x1 *x2 y1 y2 y3 y4 *y5 *x3 *x4 *x5
+ x1 x2 *y1 *y2 *y3 *y4 *y5 *x3 x4 x5
+ x1 x2 *y1 *y2 *y3 y4 *y5 x3 *x4 *x5
+ x1 x2 *y1 *y2 y3 *y4 *y5 *x3 x4 x5
ABSTRACTION
+ *x1 *x2 x3 *x4 x5
+ *x1 x2 *x3 *x4
+ *x1 x2 *x3 x4 *x5
+ x1 *x2 *x3 *x4 *x5
+ x1 x2 x3 *x4 *x5

One approach involves directly translating the definition of uniqueness:
R(x,y) and forall z . ~R(x,z) or y = z
An implementation may look like this:
def inspect(function, name, nvars):
sys.stdout.write(name) # avoid print's trailing space or newline
function.summary(nvars) # minterm count needs number of variables
function.printCover()
import sys
from cudd import Cudd
m = Cudd()
nx = 2
ny = 3
x = [m.bddVar() for i in range(nx)]
y = [m.bddVar() for i in range(ny)]
R = (~x[0] & x[1] & (~y[0] & y[1] | y[1] & y[2]) |
x[0] & ~x[1] & (y[0] ^ y[1]) & y[2] |
~x[0] & ~x[1] & y[0] & ~y[1] & ~y[2])
# This approach is independent of variable order. We are free to enable
# reordering or call it explicitly.
m.reduceHeap()
inspect(R, 'R', nx+ny)
# Create auxiliary variables and selector function.
z = [m.bddVar() for i in range(ny)]
zcube = reduce(lambda a, b: a & b, z)
P = ~m.xeqy(y,z)
# A pair is in L iff:
# - it is in R
# - there is no other pair in R with the same x and different y
L = R & ~(R.swapVariables(y,z).andAbstract(P,zcube))
inspect(L, 'L', nx+ny)
Result of running that code:
R: 10 nodes 1 leaves 6 minterms
01-11 1
10101 1
10011 1
00100 1
0101- 1
L: 6 nodes 1 leaves 1 minterms
00100--- 1
The first two variables encode the first element of the pair; the next three variables encode the second element of the pair; the last three variables are the auxiliary variables.
The code applies DeMorgan's to the formula above to make use of andAbstract.

Related

How can i fix errors with pulp Value Error: too many values to unpack?

I need help with this homework. i just can't find the error. please help me
A company produces five different types of beer and wants to maximise the possible contribution margin by optimising the production quantities. The contribution margin that can be achieved by the different types of beer is shown in the following table:
Variety DB per litre
A 1,9 €
B 1,9 €
C 1,8 €
D 1,4 €
E 1,8 €
The table below shows both the filling time (AD) and the raw material consumption (RV) for one litre of the respective beer varieties:
Variety AD RV1 RV2 RV3
A 2 1,3 1,65 1
B 1,45 1,8 1 1
C 1,2 1,55 1,3 1,4
D 1 1,2 2,1 1,5
E 1,75 1 1 1,55
The filling of the different varieties takes place on the same equipment. Theoretically, a daily bottling quantity of 4000 l of beer type A is possible while maintaining the time capacity, if no other type is produced. The daily supply of raw materials 1, 2 and 3 is as follows:
Raw material units
1 7400
2 7100
3 5900
The maximum daily demand for the products is constant and only differs between the different varieties. The maximum demand for each variety is shown in the table below:
Variety max. demand
A 2100 l
B 950 l
C 1100 l
D 1500 l
E 1550 l
Since the beer types B and C as well as the types A and D each address the same target group, a maximum of 1400 l of B and C or 2700 l of A and D should be produced in total in order to reduce the entrepreneurial risk due to a drop in sales.
Task: Describe the production problem using a linear optimisation model and determine the optimal daily production quantities of the individual beer types.
!pip install pulp
import pulp
solver_list = pulp.listSolvers(onlyAvailable=True)
print(solver_list)
lp_problem = pulp.LpProblem("LPProblem", pulp.LpMaximize)
x1 = pulp.LpVariable('x1', lowBound=0, cat='Continuous')
x2 = pulp.LpVariable('x2', lowBound=0, cat='Continuous')
x3 = pulp.LpVariable('x3', lowBound=0, cat='Continuous')
x4 = pulp.LpVariable('x4', lowBound=0, cat='Continuous')
x5 = pulp.LpVariable('x5', lowBound=0, cat='Continuous')
lp_problem += 1,9 * x1 + 1,9 * x2 + 1,8 * x3 + 1,4 * x4 + 1,8 * x5, "Z"
lp_problem += 2 * x1 <= 4000
lp_problem += 1,3 * x1 + 1,8 * x2 + 1,55 * x3 + 1,2 * x4 + 1 * x5 <= 7400
lp_problem += 1,65 * x1 + 1 * x2 + 1,3 * x3 + 2,1 * x4 + 1 * x5 <= 7100
lp_problem += 1 * x1 + 1 * x2 + 1,4 * x3 + 1,5 * x4 + 1,55 * x5 <= 5900
lp_problem += x1 <= 2100
lp_problem += x2 <= 950
lp_problem += x3 <= 1100
lp_problem += x4 <= 1500
lp_problem += x5 <= 1550
lp_problem += x1 + x4 <= 2700
lp_problem += x2 + x3 <= 1400
print(lp_problem)
lp_problem.solve()
print("Status:", pulp.LpStatus[lp_problem.status])
for variable in lp_problem.variables():
print("{} = {}".format(variable.name, variable.varValue))
print("Deckungsbeitrag =",pulp.value(lp_problem.objective))
Error Message:

Why Do i receive "Singleton variable" warning and incorrect result?

i'm writing a simple function in prolog (beginer). Function calculates a specific type of quadratic equation (but this is not important, calculations are correct).
liniowa(A, B, R, W) :-
Delta is 4*A*A*R - 4*B*B + 4*R,
( Delta < 0
-> false
; ( Delta == 0
-> X is -B/(2*A),
Y is A*X + B,
W = punkt(X, Y)
; X1 is (-B + sqrt(Delta)) / (2*A),
Y1 is A*X1 + B,
X2 is (-B - sqrt(Delta)) / (2*A),
Y2 is A*X2 + B,
writeln(X1), writeln(Y1), writeln(X2), writeln(Y2),
W = punkt(X1, Y1) ; W = punkt(X2, Y2)
)
).
When i run this function, i receive warnings:
Singleton variable in branch: X2
Singleton variable in branch: Y2
In the result i receive strange things. In writeln(X2), writeln(Y2) everything is ok, but then there is sth strange in punkt(X2, Y2):
1.4142135623730951
1.4142135623730951
-1.4142135623730951
-1.4142135623730951
W = punkt(1.4142135623730951, 1.4142135623730951)
W = punkt(_1344, _1346)
What's happening? How should I make it?
The syntax of ->/2 is horrendous at the best of times. That no official better syntax has been developed in 30 years is a sad statement, but of what? I won't say anything more about this.
It is best to separate out the program parts into separate predicates.
(A further refinement could be to separate out the case "Delta == 0" into a dedicated delta_positive(A,B,W), thus avoiding having to make a decision on delta_positive/4 and thus cutting and guarding.
liniowa(A, B, R, W) :-
Delta is 4*A*A*R - 4*B*B + 4*R,
( Delta < 0 -> false ; delta_positive(Delta,A,B,W) ).
delta_positive(0,A,B,W) :-
!, % commit to this clause
X is -B/(2*A),
Y is A*X + B,
W = punkt(X,Y).
delta_positive(Delta,A,B,W) :-
Delta \== 0, % superfluous, but makes things clear
!, % commit is also superfluous
X1 is (-B + sqrt(Delta)) / (2*A),
Y1 is A*X1 + B,
X2 is (-B - sqrt(Delta)) / (2*A),
Y2 is A*X2 + B,
format("X1=~q, Y1=~q, Y2=~q, Y2=~q\n",[X1,Y1,X2,Y2]),
(W = punkt(X1, Y1) ; W = punkt(X2, Y2)).
This immediately shows that parantheses are missing around the expression:
(W = punkt(X1, Y1) ; W = punkt(X2, Y2)).
I tried solving it:-
liniowa(A, B, R, W) :-
Delta is 4*A*A*R - 4*B*B + 4*R,
( Delta < 0
-> false
; ( Delta == 0
-> X is -B/(2*A),
Y is A*X + B,
W = punkt(X, Y)
; X1 is (-B + sqrt(Delta)) / (2*A),
Y1 is A*X1 + B,
X2 is (-B - sqrt(Delta)) / (2*A),
Y2 is A*X2 + B,
writeln(X1), writeln(Y1), writeln(X2), writeln(Y2),
W = punkt(X1, Y1) ); X2 is (-B - sqrt(Delta)) / (2*A),
Y2 is A*X2 + B, W = punkt(X2, Y2)
).
?-liniowa(2, 3, 4, W).
0.9083123951776999
4.8166247903554
-2.4083123951777
-1.8166247903553998
W = punkt(0.9083123951776999, 4.8166247903554)
W = punkt(-2.4083123951777, -1.8166247903553998)
I believe that in your code the calculation is being done in the previous step, that's why it is unable to pick it in the last case.

Rotate an image with bicubic interpolation without imrotate

I have implemented a code for image warping using bilinear interpolation:
Matlab image rotation
I would like to improve the code by using bicubic interpolation to rotate the image WITHOUT using the built-in functions like imrotate or imwarp and interp functions in MATLAB.
I successfully managed to implement a full working example.
Code is based on Anna1994's code: Matlab image rotation
Biqubic code is also based on Java (and C++) implementation posted here: http://www.paulinternet.nl/?page=bicubic
The following code applies image rotation example using biqubic interpolation:
function BicubicInterpolationTest()
close all;
% clear all;
img = 'cameraman.tif';
input_image =double(imread(img))./255;
H=size(input_image,1); % height
W=size(input_image,2); % width
th=120*pi/180; %Rotate 120 degrees
s0 = 2;
s1 = 2;
x0 = -W/2;
x1 = -H/2;
T=[1 0 x0 ; ...
0 1 x1 ; ...
0 0 1];
RST = [ (s0*cos(th)) (-s1*sin(th)) ((s0*x0*cos(th))-(s1*x1*sin(th))); ...
(s0*sin(th)) (s1*cos(th)) ((s0*x0*sin(th))+(s1*x1*cos(th))); ...
0 0 1];
M=inv(T)*RST;
N = inv(M);
output_image=zeros(H,W,size(input_image,3));
for i=1:W
for j=1:H
x = [i ; j ; 1];
y = N * x;
a = y(1)/y(3);
b = y(2)/y(3);
%Nearest neighbor
% a = round(a);
% b = round(b);
%Bilinear interpolation (applies RGB image):
% x1 = floor(a);
% y1 = floor(b);
% x2 = x1 + 1;
% y2 = y1 + 1;
% if ((x1 >= 1) && (y1 >= 1) && (x2 <= W) && (y2 <= H))
% %Load 2x2 pixels
% i11 = input_image(y1, x1, :); %Top left pixel
% i21 = input_image(y2, x1, :); %Bottom left pixel
% i12 = input_image(y1, x2, :); %Top right pixel
% i22 = input_image(y2, x2, :); %Bottom right pixel
%
% %Interpolation wieghts
% dx = x2 - a;
% dy = y2 - b;
%
% %Bi-lienar interpolation
% output_image(j, i, :) = i11*dx*dy + i21*dx*(1-dy) + i12*(1-dx)*dy + i22*(1-dx)*(1-dy);
% end
x1 = floor(a);
y1 = floor(b);
%Bicubic interpolation (applies grayscale image)
if ((x1 >= 2) && (y1 >= 2) && (x1 <= W-2) && (y1 <= H-2))
%Load 4x4 pixels
P = input_image(y1-1:y1+2, x1-1:x1+2);
%Interpolation wieghts
dx = a - x1;
dy = b - y1;
%Bi-bicubic interpolation
output_image(j, i) = bicubicInterpolate(P, dx, dy);
end
end
end
imshow(output_image);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Verify implementation by comparing with Matalb build in function imwarp:
tform = affine2d(M');
ref_image = imwarp(input_image, tform, 'OutputView', imref2d(size(input_image)), 'Interp', 'cubic');
figure;imshow(ref_image)
figure;imshow(output_image - ref_image)
max_diff = max(abs(output_image(:) - ref_image(:)));
disp(['Maximum difference from imwarp = ', num2str(max_diff)]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%http://www.paulinternet.nl/?page=bicubic
%double cubicInterpolate (double p[4], double x) {
% return p[1] + 0.5 * x*(p[2] - p[0] + x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0])));
%}
function q = cubicInterpolate(p, x)
q = p(2) + 0.5 * x*(p(3) - p(1) + x*(2.0*p(1) - 5.0*p(2) + 4.0*p(3) - p(4) + x*(3.0*(p(2) - p(3)) + p(4) - p(1))));
%http://www.paulinternet.nl/?page=bicubic
% double bicubicInterpolate (double p[4][4], double x, double y) {
% double arr[4];
% arr[0] = cubicInterpolate(p[0], y);
% arr[1] = cubicInterpolate(p[1], y);
% arr[2] = cubicInterpolate(p[2], y);
% arr[3] = cubicInterpolate(p[3], y);
% return cubicInterpolate(arr, x);
% }
function q = bicubicInterpolate(p, x, y)
q1 = cubicInterpolate(p(1,:), x);
q2 = cubicInterpolate(p(2,:), x);
q3 = cubicInterpolate(p(3,:), x);
q4 = cubicInterpolate(p(4,:), x);
q = cubicInterpolate([q1, q2, q3, q4], y);
I verified implementation by comparing to Matalb build in function imwarp
Result:
The following example uses the "CachedBicubicInterpolator" code version, and also supports RGB image:
function BicubicInterpolationTest2()
close all;
% clear all;
img = 'peppers.png';
input_image = double(imread(img))./255;
H=size(input_image,1); % height
W=size(input_image,2); % width
th=120*pi/180; %Rotate 120 degrees
s0 = 0.8;
s1 = 0.8;
x0 = -W/2;
x1 = -H/2;
T=[1 0 x0 ; ...
0 1 x1 ; ...
0 0 1];
RST = [ (s0*cos(th)) (-s1*sin(th)) ((s0*x0*cos(th))-(s1*x1*sin(th))); ...
(s0*sin(th)) (s1*cos(th)) ((s0*x0*sin(th))+(s1*x1*cos(th))); ...
0 0 1];
M=inv(T)*RST;
N = inv(M);
output_image=zeros(H,W,size(input_image,3));
for i=1:W
for j=1:H
x = [i ; j ; 1];
y = N * x;
a = y(1)/y(3);
b = y(2)/y(3);
x1 = floor(a);
y1 = floor(b);
%Bicubic interpolation (applies grayscale image)
if ((x1 >= 2) && (y1 >= 2) && (x1 <= W-2) && (y1 <= H-2))
%Load 4x4 pixels
P = input_image(y1-1:y1+2, x1-1:x1+2, :);
%Interpolation wieghts
dx = a - x1;
dy = b - y1;
%Bi-bicubic interpolation
output_image(j, i, :) = bicubicInterpolate(P, dx, dy);
end
end
end
imshow(output_image);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Verify implementation by comparing with Matalb build in function imwarp:
tform = affine2d(M');
ref_image = imwarp(input_image, tform, 'OutputView', imref2d(size(input_image)), 'Interp', 'cubic');
figure;imshow(ref_image)
figure;imshow(abs(output_image - ref_image), []);impixelinfo
max_diff = max(abs(output_image(:) - ref_image(:)));
disp(['Maximum difference from imwarp = ', num2str(max_diff)]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [p0, p1, p2, p3] = list4(P)
P = squeeze(P);
p0 = P(1, :);
p1 = P(2, :);
p2 = P(3, :);
p3 = P(4, :);
%http://www.paulinternet.nl/?page=bicubic
% public void updateCoefficients (double[][] p) {
% a00 = p[1][1];
% a01 = -.5*p[1][0] + .5*p[1][2];
% a02 = p[1][0] - 2.5*p[1][1] + 2*p[1][2] - .5*p[1][3];
% a03 = -.5*p[1][0] + 1.5*p[1][1] - 1.5*p[1][2] + .5*p[1][3];
% a10 = -.5*p[0][1] + .5*p[2][1];
% a11 = .25*p[0][0] - .25*p[0][2] - .25*p[2][0] + .25*p[2][2];
% a12 = -.5*p[0][0] + 1.25*p[0][1] - p[0][2] + .25*p[0][3] + .5*p[2][0] - 1.25*p[2][1] + p[2][2] - .25*p[2][3];
% a13 = .25*p[0][0] - .75*p[0][1] + .75*p[0][2] - .25*p[0][3] - .25*p[2][0] + .75*p[2][1] - .75*p[2][2] + .25*p[2][3];
% a20 = p[0][1] - 2.5*p[1][1] + 2*p[2][1] - .5*p[3][1];
% a21 = -.5*p[0][0] + .5*p[0][2] + 1.25*p[1][0] - 1.25*p[1][2] - p[2][0] + p[2][2] + .25*p[3][0] - .25*p[3][2];
% a22 = p[0][0] - 2.5*p[0][1] + 2*p[0][2] - .5*p[0][3] - 2.5*p[1][0] + 6.25*p[1][1] - 5*p[1][2] + 1.25*p[1][3] + 2*p[2][0] - 5*p[2][1] + 4*p[2][2] - p[2][3] - .5*p[3][0] + 1.25*p[3][1] - p[3][2] + .25*p[3][3];
% a23 = -.5*p[0][0] + 1.5*p[0][1] - 1.5*p[0][2] + .5*p[0][3] + 1.25*p[1][0] - 3.75*p[1][1] + 3.75*p[1][2] - 1.25*p[1][3] - p[2][0] + 3*p[2][1] - 3*p[2][2] + p[2][3] + .25*p[3][0] - .75*p[3][1] + .75*p[3][2] - .25*p[3][3];
% a30 = -.5*p[0][1] + 1.5*p[1][1] - 1.5*p[2][1] + .5*p[3][1];
% a31 = .25*p[0][0] - .25*p[0][2] - .75*p[1][0] + .75*p[1][2] + .75*p[2][0] - .75*p[2][2] - .25*p[3][0] + .25*p[3][2];
% a32 = -.5*p[0][0] + 1.25*p[0][1] - p[0][2] + .25*p[0][3] + 1.5*p[1][0] - 3.75*p[1][1] + 3*p[1][2] - .75*p[1][3] - 1.5*p[2][0] + 3.75*p[2][1] - 3*p[2][2] + .75*p[2][3] + .5*p[3][0] - 1.25*p[3][1] + p[3][2] - .25*p[3][3];
% a33 = .25*p[0][0] - .75*p[0][1] + .75*p[0][2] - .25*p[0][3] - .75*p[1][0] + 2.25*p[1][1] - 2.25*p[1][2] + .75*p[1][3] + .75*p[2][0] - 2.25*p[2][1] + 2.25*p[2][2] - .75*p[2][3] - .25*p[3][0] + .75*p[3][1] - .75*p[3][2] + .25*p[3][3];
% }
% public double getValue (double x, double y) {
% double x2 = x * x;
% double x3 = x2 * x;
% double y2 = y * y;
% double y3 = y2 * y;
%
% return (a00 + a01 * y + a02 * y2 + a03 * y3) +
% (a10 + a11 * y + a12 * y2 + a13 * y3) * x +
% (a20 + a21 * y + a22 * y2 + a23 * y3) * x2 +
% (a30 + a31 * y + a32 * y2 + a33 * y3) * x3;
% }
function q = bicubicInterpolate(P, x, y)
[p00, p01, p02, p03] = list4(P(1, :, :));
[p10, p11, p12, p13] = list4(P(2, :, :));
[p20, p21, p22, p23] = list4(P(3, :, :));
[p30, p31, p32, p33] = list4(P(4, :, :));
a00 = p11;
a01 = -.5*p10 + .5*p12;
a02 = p10 - 2.5*p11 + 2*p12 - .5*p13;
a03 = -.5*p10 + 1.5*p11 - 1.5*p12 + .5*p13;
a10 = -.5*p01 + .5*p21;
a11 = .25*p00 - .25*p02 - .25*p20 + .25*p22;
a12 = -.5*p00 + 1.25*p01 - p02 + .25*p03 + .5*p20 - 1.25*p21 + p22 - .25*p23;
a13 = .25*p00 - .75*p01 + .75*p02 - .25*p03 - .25*p20 + .75*p21 - .75*p22 + .25*p23;
a20 = p01 - 2.5*p11 + 2*p21 - .5*p31;
a21 = -.5*p00 + .5*p02 + 1.25*p10 - 1.25*p12 - p20 + p22 + .25*p30 - .25*p32;
a22 = p00 - 2.5*p01 + 2*p02 - .5*p03 - 2.5*p10 + 6.25*p11 - 5*p12 + 1.25*p13 + 2*p20 - 5*p21 + 4*p22 - p23 - .5*p30 + 1.25*p31 - p32 + .25*p33;
a23 = -.5*p00 + 1.5*p01 - 1.5*p02 + .5*p03 + 1.25*p10 - 3.75*p11 + 3.75*p12 - 1.25*p13 - p20 + 3*p21 - 3*p22 + p23 + .25*p30 - .75*p31 + .75*p32 - .25*p33;
a30 = -.5*p01 + 1.5*p11 - 1.5*p21 + .5*p31;
a31 = .25*p00 - .25*p02 - .75*p10 + .75*p12 + .75*p20 - .75*p22 - .25*p30 + .25*p32;
a32 = -.5*p00 + 1.25*p01 - p02 + .25*p03 + 1.5*p10 - 3.75*p11 + 3*p12 - .75*p13 - 1.5*p20 + 3.75*p21 - 3*p22 + .75*p23 + .5*p30 - 1.25*p31 + p32 - .25*p33;
a33 = .25*p00 - .75*p01 + .75*p02 - .25*p03 - .75*p10 + 2.25*p11 - 2.25*p12 + .75*p13 + .75*p20 - 2.25*p21 + 2.25*p22 - .75*p23 - .25*p30 + .75*p31 - .75*p32 + .25*p33;
x2 = x * x;
x3 = x2 * x;
y2 = y * y;
y3 = y2 * y;
% q = (a00 + a01 * y + a02 * y2 + a03 * y3) +...
% (a10 + a11 * y + a12 * y2 + a13 * y3) * x +...
% (a20 + a21 * y + a22 * y2 + a23 * y3) * x2 +...
% (a30 + a31 * y + a32 * y2 + a33 * y3) * x3;
q = (a00 + a01 * x + a02 * x2 + a03 * x3) +...
(a10 + a11 * x + a12 * x2 + a13 * x3) * y +...
(a20 + a21 * x + a22 * x2 + a23 * x3) * y2 +...
(a30 + a31 * x + a32 * x2 + a33 * x3) * y3;
Result:

Generate numbers in Ruby that aren't equal to other numbers?

Basically I am generating numbers and they can't be equal to any other numbers I've generated. Is there a quicker way to do this because it looks slightly ridiculous.
Thanks
#possible generated values
x1 = 0
x2 = 1
x3 = 2
#generate co-ordinates
x4 = rand(7)
until x4 != x1 && x4 != x1+1 && x4 != x1+2 && x4 != x2 && x4 != x2+1 && x4 != x2+2 && x4 != x3 && x4 != x3+1 && x4 != x3+2 do
x4 = rand(7)
end
#possible generated values
y1 = 0
y2 = 1
y3 = 2
y4 = rand(7)
until y4 != y1 && y4 != y1+1 && y4 != y1+2 && y4 != y2 && y4 != y2+1 && y4 != y2+2 && y4 != y3 && y4 != y3+1 && y4 != y3+2 do
y4 = rand(7)
end
For Ruby 1.9+
(0..6).to_a.sample(x)
or for older versions
(0..6).to_a.shuffle.take(x)
where x is the number of integers you want to take. Since rand(7) does not include the number 7, you need your range to be one less than the number you'd pass to rand.
And obviously you can't take more numbers than are in the range.

Print GLPK objective/constraints in human readable format

I'm using GLPK C API for a mixed integer programming problem. Is there some way to print the objective/constraints in human readable format for debugging?
Perhaps the nicest format is the CPLEX LP format. It looks something like this:
Maximize
obj: x1 + 2 x2 + 3 x3 + x4
Subject To
c1: - x1 + x2 + x3 + 10 x4 <= 20
c2: x1 - 3 x2 + x3 <= 30
c3: x2 - 3.5 x4 = 0
Bounds
0 <= x1 <= 40
2 <= x4 <= 3
General
x4
End
You can write your model in this format by calling:
int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname);
See also glp_write_lp — write problem data in CPLEX LP format in the documentation that comes with GLPK.

Resources