set the values to binary - matlab

for s=1:length(C_tem)
for w=1:length(C_tem{s})
if (abs(C_tem{s}{w}) >= 0)
C_tem{s}{w} = 1;
else
C_tem{s}{w} = 0;
end
end
end
I am trying to set the values larger than 0 to 1, and if less or equal to 0, but for some reason this doesn't work.
I'm new in matlab, and I really need the help if possible. Thank you in advance..

i havn't worked on matlab much but this part of code feels suspicious -
if (abs(C_tem{s}{w}) >= 0)
C_tem{s}{w} = 1;
else
C_tem{s}{w} = 0;
end
Why are you doing abs here? I think it will remove sign from number. Code should be something like this-
if (C_tem{s}{w} > 0) //I have removed abs and >= is replaced with >
C_tem{s}{w} = 1;
else
C_tem{s}{w} = 0;
end

abs(x)>=0 is true for all values of x. The simple answer is to remove the abs. The more complete answer follows up on Dan's comment. The cell array is unnecessary at the inner level. If you instead had a cell array of regular arrays, then you could do this for the entire block of code.
for s=1:length(C_tem)
C_tem{s} = (C_tem{s} >= 0);
end
Two things to notice: comparison operators are vectorized, meaning they return a matrix of the same size as the input, thus comparing all values at once. And, the output of the operator is 1 where true and 0 where false.
Also look at the builtin function sign to see if that's closer to what you want to do.

Related

MATLAB Structure array blackjack

I'm writing a program to play blackjack and one of the functions calculates the score. It takes in an input which is a structure array of cards and one of the attributes is value (for an ace the value is 11). My function is supposed to determine if the total of the values is over 21 and if 1 of the cards is an ace, then the ace's value is changed to 1. Can anyone help me figure this out please?
for index=1:length(input)
if(input(input).value == 11)
input(index).value = 1;
end;
end;
You're not actually summing the cards in your original snippet. You also seem to have a typo in input(input), I think this should be input(index). If you wanted to do it with a for loop like you have, you'd do something like this:
total = 0;
for index=1:length(input)
if(input(index).value == 11)
input(index).value = 1;
end;
total = total + input(index);
end;
The more MATLAB way of doing things would be to avoid loops by using the sum in-built command.

How can I re-write this MATLAB code in a more idiomatic and efficient way?

Here is the requirement: the input is a number which will divide an image into several equal part. For example, if the input is 4, it will return 3 parts: the values are the imgSize/4 imgSize/4 * 2 and imgSize/4 * 3.
If the input is n, then it will return n - 1 elements, as in the following implementation:
if (colorLevel == 8)
divide_thres = [ round(imgSize/8) round(imgSize/8)*2 round(imgSize/8)*3 round(imgSize/8)*4
round(imgSize/8)*5 round(imgSize/8)*6 round(imgSize/8)*7 ];
elseif (colorLevel == 4)
divide_thres = [ round(imgSize/4) round(imgSize/4)*2 round(imgSize/4)*3 ];
elseif (colorLevel == 3)
divide_thres = [ round(imgSize/3) round(imgSize/3)*2 ];
end
I want to allow the user to input a value between 2 and 255, and then automatically generate the divide_thres corresponding to that input. How can I re-write this code to be more efficient?
There are several problems with your code:
In each case, you unnecessarily divide imgSize by the same factor multiple times (instead of just once and for all).
You perform many "manual" scalar multiplications, but you could simply multiply the scalar value by a vector generated by the range 1 : colorLevel - 1.
Because the length of the resulting divide_thres vector can be easily computed from the value of colorLevel, there is no need to treat each case separately in an if statement.
Moreover, even if you had to compute the length in a different manner for the cases imgSize = 3, 4, and 8, you would be better off using a switch statement instead of an if statement, because the former would save you the trouble of writing imgSize == ... each time, which is prone to errors and a form of code duplication.
Here's a much simplified approach:
if 2 <= colorLevel && colorLevel <= 255
divide_thres = round(imgSize / colorLevel) * (1 : colorLevel - 1);
else
error('invalid colorLevel value') % (or some other informative message)
end
This should do it -
divide_thres = [1:colorLevel-1]*round(imgSize/colorLevel)

Matlab: Loop issue

This is quite a simple issue, but I've been struggling with it. sortedd and sortedfinal_d are 8 x 1000 Matrices and I am using the loop below to check if any of the elements in sortedfinal_d lies between two consecutive elements of sortedd, in terms of magnitude. I'm doing this along each row. overall_p is a 8 x 1000 Matrix as well, but at the end of this process I end up having final_p as a Matrix of Zeros. I don't know why this is.
for k=2:1000
for s=1:1000
for j=1:8
if sortedd(j,k) > sortedfinal_d(j,s) && sortedfinal_d(j,s) > sortedd(j,k-1)
final_p(j,s) = overall_p(j,k);
end
end
end
end
EDIT: Added data for the inputs as shown below:
sortedd (first four columns) =
0.219977361620113 0.219996752039812 0.220344444223787 0.220593274018691
0.272807483153955 0.273682693068593 0.273846498221277 0.274060049642900
0.327201460264565 0.327375792227635 0.327572790857546 0.327856448530021
0.380389118311424 0.380845274148177 0.380893687870765 0.381015090963159
0.434832574575088 0.434860658844550 0.435021604722982 0.435119929919457
0.487119089589798 0.488128501559782 0.488207451439073 0.488430455768512
0.540652551559395 0.541303305046034 0.542195194863130 0.542234381085921
0.595254195563241 0.595296064375604 0.595376090156252 0.595377962767971
sortedfinal_d =
0.182086792394190 0.182406508309366 0.182406508309366 0.182808976400818
0.233058295607543 0.233058295607543 0.233158455616954 0.233158455616954
0.286243848617693 0.286357973626582 0.286918095670684 0.287393171241241
0.336938335090164 0.336938335090164 0.337094505106945 0.337669618738100
0.390287818652551 0.390567879874952 0.390567879874952 0.390670502700602
0.446995120903824 0.447270251510681 0.447452123072880 0.447597175111267
0.501060785098551 0.501060785098551 0.501060785098551 0.501060785098551
0.551311219045087 0.551463923687602 0.551463923687602 0.551653815175502
Thanks a lot
Do you have to use loops to accomplish this?
matching_d = sortedfinal_d(:,1:end-1) < sortedd(:,2:end) ...
& sortedd(:,2:end) < sortedfinal_d(:,2:end);
final_p(matching_d) = overall_p(matching_d);
If you can show us a small sample input (say, 1x5 versions of sortedd and sortedfinal_d) and output (the corresponding matching_d) it would be easier for us to help troubleshoot.
If i set your matrices to random numbers, final_p does return some numbers.
So your code works as is. Post your dataset or at least describe the dataset in some detail, this will make it much easier to diagnose the problem.
I have reduced 1000 down to 10 and re-ordered the iteration variables to i, j, k to make it easier to follow:
sortedd = rand(8, 10);
sortedfinal_d = rand(8, 10);
overall_p = rand(8, 10);
for i=2:10
for j=1:10
for k=1:8
if sortedd(k,i) > sortedfinal_d(k,j) && sortedfinal_d(k,j) > sortedd(k,i-1)
final_p(k,j) = overall_p(k,i);
end
end
end
end
final_p

Have for loop script do something only every Nth iteration

In MATLAB (or more generally) if I wanted something to happen only, for example, every 50 iterations of a for loop how could I do this better than below? That is to not write out every possible value of +50. Thanks.
for i = 1:1060;
if i = 50 || 100 || 150 || ... || 1050
randi(i); % for example, just do something
end;
end;
What you want is
if mod(i, 50) == 0
do something
What you want is
for i = 0:50:1050
do_stuff(i);
end
unless, it is unclear from your question, if the previous answer is what you really want, which you might need in the case that looks like this
for i = 1:1060
if mod(i, 50) == 0
do_something(i)
end
do_something_else(i)
end
Cheers,--

Sudoku solver evaluation function

So I'm trying to write a simple genetic algorithm for solving a sudoku (not the most efficient way, I know, but it's just to practice evolutionary algorithms). I'm having some problems coming up with an efficient evaluation function to test if the puzzle is solved or not and how many errors there are. My first instinct would be to check if each row and column of the matrix (doing it in octave, which is similar to matlab) have unique elements by ordering them, checking for duplicates and then putting them back the way they were, which seems long winded. Any thoughts?
Sorry if this has been asked before...
Speedups:
Use bitwise operations instead of sorting.
I made 100 line sudoku solver in c it reasonably fast. For or super speed you need to implement DLX algorhitm, there is also some file on matlab exchange for that.
http://en.wikipedia.org/wiki/Exact_cover
http://en.wikipedia.org/wiki/Dancing_Links
http://en.wikipedia.org/wiki/Knuth's_Algorithm_X
#include "stdio.h"
int rec_sudoku(int (&mat)[9][9],int depth)
{
int sol[9][9][10]; //for eliminating
if(depth == 0) return 1;
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
sol[i][j][9]=9;
for(int k=0;k<9;k++)
{
if(mat[i][j]) sol[i][j][k]=0;
else sol[i][j][k]=1;
}
}
}
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(mat[i][j] == 0) continue;
for(int k=0;k<9;k++)
{
if(sol[i][k][mat[i][j]-1])
{
if(--sol[i][k][9]==0) return 0;
sol[i][k][mat[i][j]-1]=0;
}
if(sol[k][j][mat[i][j]-1])
{
if(--sol[k][j][9]==0) return 0;
sol[k][j][mat[i][j]-1]=0;
}
}
for(int k=(i/3)*3;k<(i/3+1)*3;k++)
{
for(int kk=(j/3)*3;kk<(j/3+1)*3;kk++)
{
if(sol[k][kk][mat[i][j]-1])
{
if(--sol[k][kk][9]==0) return 0;
sol[k][kk][mat[i][j]-1]=0;
}
}
}
}
}
for(int c=1;c<=9;c++)
{
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
if(sol[i][j][9] != c) continue;
for(int k=0;k<9;k++)
{
if(sol[i][j][k] != 1) continue;
mat[i][j]=k+1;
if(rec_sudoku(mat,depth-1)) return 1;
mat[i][j]=0;
}
return 0;
}
}
}
return 0;
}
int main(void)
{
int matrix[9][9] =
{
{1,0,0,0,0,7,0,9,0},
{0,3,0,0,2,0,0,0,8},
{0,0,9,6,0,0,5,0,0},
{0,0,5,3,0,0,9,0,0},
{0,1,0,0,8,0,0,0,2},
{6,0,0,0,0,4,0,0,0},
{3,0,0,0,0,0,0,1,0},
{0,4,0,0,0,0,0,0,7},
{0,0,7,0,0,0,3,0,0}
};
int d=0;
for(int i=0;i<9;i++) for(int j=0;j<9;j++) if(matrix[i][j] == 0) d++;
if(rec_sudoku(matrix,d)==0)
{
printf("no solution");
return 0;
}
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
printf("%i ",matrix[i][j]);
}
printf("\n");
}
return 1;
}
The check is easy, you'll create sets for rows, columns, and 3x3's adding a number if it does not exist and altering your fitness accordingly if it does not.
The real trick however is "altering your fitness" accordingly. Some problems seem well suited to GA and ES (evolution strategies), that is we look for a solution in tolerance, sudoku has an exact answer... tricky.
My first crack would probably be creating solutions with variable length chromosomes (well they could be fixed length but 9x9's with blanks). The fitness function should be able to determine which part of the solution is guaranteed and which part is not (sometimes you must take a guess in the dark in a really tough sudoku game and then back track if it does not work out), it would be a good idea to create children for each possible branch.
This then is a recursive solution. However you could start scanning from different positions on the board. Recombination would combine solutions which combine unverified portions which have overlapping solutions.
Just thinking about it in this high level easy going fashion I can see how mind bending this will be to implement!
Mutation would only be applied when there is more than one path to take, after all a mutation is a kind of guess.
Sounds good, except for the 'putting them back' part. You can just put the numbers from any line, column or square in the puzzle in a list and check for doubles any way you want. If there are doubles, there is an error. If all numbers are unique there's not. You don't need to take the actual numbers out of the puzzle, so there is no need for putting them back either.
Besides, if you're writing a solver, it should not make any invalid move, so this check would not be needed at all.
I would use the grid's numbers as an index, and increment an 9 elements length array's respective element => s_array[x]++ where x is the number taken from the grid.
Each and every element must be 1 in the array at the end of checking one row. If 0 occurs somewhere in the array, that line is wrong.
However this is just a simple sanity check if there are no problems, line-wise.
PS: if it were 10 years ago, I would suggest an assembly solution with bit manipulation (1st bit, 2nd bit, 3rd bit, etc. for the values 1,2 or 3) and check if the result is 2^10-1.
When I solved this problem, I just counted the number of duplicates in each row, column and sub-grid (in fact I only had to count duplicates in columns and sub-grids as my evolutionary operators were designed never to introduce duplicates into rows). I just used a HashSet to detect duplicates. There are faster ways but this was quick enough for me.
You can see this visualised in my Java applet (if it's too fast, increase the population size to slow it down). The coloured squares are duplicates. Yellow squares conflict with one other square, orange with two other squares and red with three or more.
Here is my solution. Sudoku solving solution in C++
Here is my solution using set. If for a line, a block or a column you get a set length of (let say) 7, your fitness would be 9 - 7.
If you are operating on a small set of integers sorting can be done in O(n) using bucket sorting.
You can use tmp arrays to do this task in matlab:
function tf = checkSubSet( board, sel )
%
% given a 9x9 board and a selection (using logical 9x9 sel matrix)
% verify that board(sel) has 9 unique elements
%
% assumptions made:
% - board is 9x9 with numbers 1,2,...,9
% - sel has only 9 "true" entries: nnz(sel) = 9
%
tmp = zeros(1,9);
tmp( board( sel ) ) = 1; % poor man's bucket sorting
tf = all( tmp == 1 ) && nnz(sel) == 9 && numel(tmp) == 9; % check validity
Now we can use checkSubSet to verify the board is correct
function isCorrect = checkSudokuBoard( board )
%
% assuming board is 9x9 matrix with entries 1,2,...,9
%
isCorrect = true;
% check rows and columns
for ii = 1:9
sel = false( 9 );
sel(:,ii) = true;
isCorrect = checkSubSet( board, sel );
if ~isCorrect
return;
end
sel = false( 9 );
sel( ii, : ) = true;
isCorrect = checkSubSet( board, sel );
if ~isCorrect
return;
end
end
% check all 3x3
for ii=1:3:9
for jj=1:3:9
sel = false( 9 );
sel( ii + (0:2) , jj + (0:2) ) = true;
isCorrect = checkSubSet( board, sel );
if ~isCorrect
return;
end
end
end