In Matlab, I need to find all possible combinations of a vector that satisfies some constraints that I find quite irregular.
The vector, x, has 12 entries: x_0,x_1,...,x_11
Local constraints:
x_0 in {1,...,6}
x_i in {0,...,6}, i = 1,...,6
x_j in {0,...,12-j}, j = 7,...,11
Global constraints:
sum(x) = 12
for any k, x_k = y ==> x_{k+j} = 0 for j = 1,...,y-1
I have thought about this for quite a while now and can't seem to solve it myself - any ideas anyone?
Use recursion and intermediate constraint checking. Something like this does the trick:
function dispConstraintSatisfyingVectors()
global lb ub sumVal
lb = [1 0 0 0 0 0 0 0 0 0 0 0];
ub = [6 6 6 6 6 6 6 5 4 3 2 1];
sumVal = 12;
x = zeros(1,12);
addValueRecursive(x,1);
end
function addValueRecursive(x,idx)
global lb ub sumVal
for val = lb(idx):ub(idx)
x(idx) = val;
if checkZerosConstraint(x) == 0 && sum(x) <= sumVal
if idx < 12
addValueRecursive(x,idx+1);
else
if sum(x) == sumVal
disp(num2str(x))
end
end
end
end
end
function c = checkZerosConstraint(x)
c = 0;
for j=1:11
c = c + sum(x(j+1:j+x(j)-1));
end
end
Related
I have created a function to add one to an element as follows;
function xz = addOne(x)
nrow = size(x,1);
ncol = size(x,1);
for K = 1:nrow
for J = 1:ncol
xz = x(:) + 1;
end
end
Example: given 1 the function results in 2:
addOne(1) [2]
I have tried using a matrix as an argument for the function...
x = [1 2 3; 0 0 0; 4 5 6];
x =
1 2 3
0 0 0
4 5 6
addOneWithFors(x)
ans =
2
1
5
3
1
6
4
1
7
How would I update this function to accept a matrix with multiple rows and columns and output it as such instead of just 1 number or a list of elements. Any help would be greatly appreciated.
In Matlab, you don't need a special function to do this. Matlab natively supports adding a scalar to a matrix. For example:
x = [1 2 3; 0 0 0; 4 5 6];
y = x + 1
will produce:
y =
2 3 4
1 1 1
5 6 7
However, if you specifically want to write this out explicitly using for loops, then your addOne() function only needs minor modifications. For example:
function xz = addOne(x)
nrow = size(x,1);
ncol = size(x,2);
xz = zeros(nrow,ncol);
for K = 1:nrow
for J = 1:ncol
xz(K,J) = x(K,J) + 1;
end
end
Note that ncol = size(x,2); has been defined correctly.
I have been studying Matlab for hobby.
This is my second question in stack-overflow.
These days I have interest in Sudoku by Matlab.
I got code from internet and I am studying this code for 3 weeks.
I want to add function which indicate how many times 'sub-function(candidates)' executed. -> how many times function works for solution.
I used to use cnt = 0 and cnt=cnt+1 for count(under if statement and while statement)
but i realize this code's structure is loop(??)
*i tried it but cnt were reset when i try, i think i know the reason of reset
but i can't write it code
Thank you for your help
function X = s2(X)
% SUDOKU Solve Sudoku using recursive backtracking.
% sudoku(X), expects a 9-by-9 array X.
% Fill in all ?singletons?.
% C is a cell array of candidate vectors for each cell.
% s is the first cell, if any, with one candidate.
% e is the first cell, if any, with no candidates.
[C,s,e] = candidates(X);
while ~isempty(s) && isempty(e)
X(s) = C{s};
[C,s,e] = candidates(X);
end
% Return for impossible puzzles.
if ~isempty(e)
return
end
% Recursive backtracking.
if any(X(:) == 0)
Y = X;
z = find(X(:) == 0,1); % The first unfilled cell.
for r = [C{z}] % Iterate over candidates.
X = Y;
X(z) = r; % Insert a tentative value.
X = s2(X); % Recursive call.
if all(X(:) > 0) % Found a solution.
return
end
end
end
% ???????????????
function [C,s,e] = candidates(X)
C = cell(9,9);
tri = #(k) 3*ceil(k/3-1) + (1:3);
for j = 1:9
for i = 1:9
if X(i,j)==0
z = 1:9;
z(nonzeros(X(i,:))) = 0;
z(nonzeros(X(:,j))) = 0;
z(nonzeros(X(tri(i),tri(j)))) = 0;
C{i,j} = nonzeros(z)';
end
end
end
L = cellfun(#length,C); % Number of candidates.
s = find(X==0 & L==1,1);
e = find(X==0 & L==0,1);
end % candidates
end % s2
i used variable X
X=[4 0 0 0 2 0 0 0 0;
0 1 0 3 0 0 5 0 0;
0 0 9 0 0 8 0 6 0;
7 0 0 6 0 0 1 0 0;
0 2 0 0 0 0 0 0 9;
0 0 3 0 0 4 0 0 0;
6 0 0 7 0 0 0 2 0;
0 8 0 0 1 0 0 0 4;
0 0 0 0 0 9 3 0 0];
You could also use a persistent variable, which should retain its value across multiple calls of the function.
For example:
function [ result ] = myfactorial( num )
% using persistent variable based on
% https://www.mathworks.com/help/matlab/ref/persistent.html
persistent numcalls;
if isempty(numcalls)
numcalls = 0;
end
numcalls = numcalls+1;
disp(strcat('numcalls is now: ', int2str(numcalls)));
% factorial function based on
% https://www.quora.com/How-can-I-create-a-factorial-function-in-MATLAB
if num > 1
result = myfactorial(num-1)*num;
else
result = 1;
end
end
Now call the function.
clear all;
result = myfactorial(5);
The output is:
numcalls is now:1
numcalls is now:2
numcalls is now:3
numcalls is now:4
numcalls is now:5
i want to declare that x will be variable for binary 0,1
i and k represent facilities in flow matrix, j and q represent location in distance matrix ..
x(i,j) mean that x will be equal to 1 if i (facility) is assign in j (location) ..
x(i, j) = 1 if facility i is assigned to location j and if otherwise, xij = 0,
so otherwise mean that if x(k,q) =1 , x(i,J) will be 0...
example of the manual calculation
Min =(f i1,k1 * d j1,q1 * x i1,j1 * x k1,q1) + (f i1,k1 * d j1,q2 * x i1,j1 * x k1,q2) + (f i1,k1 * d j1,q3 * x i1,j1 * x k1,q3)....
( 0*0* 1*1 ) + ( 0* 6* 1*0 ) + ( 0*8 * 1 *0 ).....
I want to *xi1,j1 * xk1,q1 to be 0 or 1.. if i choose i1, j1=1 the other will be 0.. for example i2,j1 will be equal to 0
below is the coding
clc;
clear;
%sum sum sum sum(fik*djq*xij*xkq)
%i,k= facilities
%j,q= location
%f(i,k)= flow between facilities i and k
%d(j,q)= distance between locations j and q
%xij = 1 if facility i is assigned to location j and if otherwise, xij = 0
% Flow matrix: flow assigning facility i (column) to facility k (row)
f = [0 5 7 9;
5 0 4 6;
7 4 0 3;
9 6 3 0];
%Distance matrix: distance assigning location j (column) to location q (row)
d = [0 6 8 9;
6 0 5 1;
8 5 0 2;
9 1 2 0];
z= 0;
nf= 4;
nd= 4;
for i=1:nf
for j=1:nf
for k=1:nd
for q=1:nd
z = min('z','f(i,k)*d(j,q)*x(i,j)*x(k,q)');
end
end
end
end
%Constraints
%The first set of constraints requires that each facility gets exactly one
%location, that is for each facility, the sum of the location values
%corresponding to that facility is exactly one
Constraints.constr1 = sum(x,2) == 1;
%The second set of constraints are inequalities. These constraints specify
%that each office has no more than one facility in it.
Constraints.constr2 = sum(x,1) == 1;
disp (z);
by using recperm
this recperm is used to fine permuation 0,1 in the coding
Can someone help me to provide an efficient way or help me to perform the provide code to do make same results in minimal possible steps. I shall be grateful to you.
I have an Original Array:
A = [1 1 1 4.3 4.5 4 4.3 3 1 0 0 2 6.2 6.3 6 6.2 7.4 8 7.2 2 2 3 3 2];
Output Looks like:
A = [1 1 1 4 4 4 4 3 1 0 0 2 6 6 6 6 6 7 7 2 2 3 3 2];
I apply some restrictions and removed some values from array of local maxima’s after that I received some new arrays.
Yposlocfiltered = [6 15 23];
idx = [4 6 3];
Yneglocfiltered = [2 9 20];
idx_neg = [1 1 2];
Where I will find idx(local maxima value) I will check if values behind and ahead are greater make a window.
Example
If I will find 4 and 4.5, 4.3 is greater than 4 include it in backward window
4.3 is greater than 4 include it in forward window.
I need to find range of values behind local maxima and ahead local maxima.
I have tried to write a code that’s works fine but issue is that it’s too long.
Can someone please provide me an idea to perform this action in minimal steps and in faster ways?
I have only provided code for positive local maxima’s as for negative local maxima code Is just replica of this.
Code:only for positive local maximas
clc
clear all
A = [1 0 1 4.3 4.5 5 4.3 3 0 0 0 2 6.2 6.3 7 6.2 7.4 8 7.2 1 2 3 4 2];
Yposlocfiltered = [ 6 15 23];
idx = [4 6 3];
Yneglocfiltered = [2 9 20];
idx_neg = [1 1 2];
for b = 1: numel(idx)
for c = 1:numel(A)
f = Yposlocfiltered(1,b)-c ;
g = Yposlocfiltered(1,b)+c ;
% if (f > 0 && g <= numel(X))
if(f > 0)
if (A(Yposlocfiltered(1,b)-c))> idx(1,b)
else
d= f+1;
z(b)= d;
backward_window = z;
break
end
end
end
end
for r = 1: numel(idx)
for s = 1:numel(A)
u = Yposlocfiltered(1,r)-s ;
v = Yposlocfiltered(1,r)+s ;
% if (f > 0 && g <= numel(X))
if(v <=numel(A))
if (A(Yposlocfiltered(1,r)+s))> idx(1,r)
else
w= v-1;
y(r)= w;
forward_window = y;
break
end
end
end
end
n=4
for i=1:length(backward_window)
range = backward_window(i): forward_window(i);
p = range
if n <= numel(p)
p = range(1:n)
A( p) = idx(i);
else
% if (size(range)<= 3)
A( p) = idx(i);
end
end
From the first look at your code, I believe you can combine your first two for loops into one.
sA = numel(A);
sI = numel(idx);
for i = 1:sI
f = Yposlocfiltered(i) - [1:sA];
g = Yposlocfiltered(i) + [1:sA];
f(f<1) = [];
g(g>sA) = [];
backward_window(i) = f(find(A(f) <= idx(i), 1)) + 1;
forward_window(i) = g(find(A(g) <= idx(i), 1)) - 1;
end
Here, you can use find to locate the element of an array matching the specified condition, i.e. g <= numel(X) or A(f) <= idx(i).
Your last loop which modifies A can also be integrated into the same loop, so you can have:
sA = numel(A);
sI = numel(idx);
n=4;
for i = 1:sI
f = Yposlocfiltered(i) - [1:sA];
g = Yposlocfiltered(i) + [1:sA];
f(f<1) = [];
g(g>sA) = [];
backward_window(i) = f(find(A(f) <= idx(i), 1)) + 1;
forward_window(i) = g(find(A(g) <= idx(i), 1)) - 1;
range = backward_window(i) : forward_window(i);
if n <= numel(range)
A(range(1:n)) = idx(i);
else
A(range) = idx(i);
end
end
I have the following code that includes 3 iterated for loops in order to create an upper diagonal matrix, I plan on performing on large data set many times and want to make as computationally efficient as possible.
data = magic(3);
n = size(data,1);
W = zeros(n,n);
for i = 1:n
for j = i:n
if i==j
W(i,j)=0;
else
for k = 1:n
temp(1,k) = (data(i,k)-data(j,k))^2;
sumTemp = sumTemp + temp(1,k);
end
W(i,j)=sqrt(sumTemp);
end
temp = 0;
sumTemp = 0;
end
end
Answer should look like:
[0 6.4807 9.7980
0 0 6.4807
0 0 0]
I am working it hard right now, but figure I would throw it out there in case anyone has any suggestions that would save me hours of fiddling around.
This is hat I have at the moment:
data = magic(3);
n = size(data,1);
W = zeros(n,n);
for i = 1:n
for j = i+1:n
W(i,j)= norm(data(i,:)-data(j,:))
%W(i,j)= sqrt(sum((data(i,:)-data(j,:)).^2));
end
end
What I did:
vecorized the inner loop
removed www, which is unused
changed 2nd loop, start at i+1 because nothing is done for i=j
Replaced sqrt((a-b).^2) with norm(a-b)
And now the "full" vectorization:
data = magic(3);
n = size(data,1);
W = zeros(n,n);
tri=triu(ones(n,n),1)>0;
[i,j]=find(tri);
W(tri)=arrayfun(#(i,j)norm(data(i,:)-data(j,:)),i,j)
Here is a straightforward solution with bsxfun:
Wfull = sqrt(squeeze(sum(bsxfun(#minus,data,permute(data,[3 2 1])).^2,2)))
W = triu(Wfull)
Use this where data is N-by-D, where N is the number of points and D is dimensions. For example,
>> data = magic(3);
>> triu(sqrt(squeeze(sum(bsxfun(#minus,data,permute(data,[3 2 1])).^2,2))))
ans =
0 6.4807 9.7980
0 0 6.4807
0 0 0
>> data = magic(5); data(:,end-1:end)=[]
data =
17 24 1
23 5 7
4 6 13
10 12 19
11 18 25
>> triu(sqrt(squeeze(sum(bsxfun(#minus,data,permute(data,[3 2 1])).^2,2))))
ans =
0 20.8087 25.2389 22.7376 25.4558
0 0 19.9499 19.0263 25.2389
0 0 0 10.3923 18.3576
0 0 0 0 8.5440
0 0 0 0 0
>>