I have a function that takes a 2d array as an input, and outputs the array with the sign of random coordinates flipping. I want to repeat this function n times, with it taking the output of the function as the input for the next time. How am i able to do this? The array S is an n*n array of randomised 1s and -1s
Thermal<-function(S,t=0.000000000001,k=1){
#Defing beta
beta<-1/(k*t)
#multiplying each point of the array by all its adjacent points
#and summing them
Spointenergy<-S*((S2)+(S3)+S4+S5)
#Creating a loop over the whole array
for(i in 1:n){
for (j in 1:n){
#defining the change in energy at each point
dE<-energychange(S,i,j)
#By default each point does not flip
accept<-FALSE
#If energy decreases spin flip occurs 100% of the time
if (dE<0){
accept<-TRUE
}
#If energy increases a spin flip will occur if w is greater than or equal
#to u.
if (dE>=0){
w<-exp(-beta*dE)
u<-runif(1,0,1)
if (w>=u){
accept<-TRUE
}
}
#If no spin flip occurs there is no change in energy
if (accept==FALSE){
dE<-0
}
#if spin flip does occur then the magnitude of each lattice point is flipped
#from positive to negative or visa versa
if (accept==TRUE){
S[i,j]<--S[i,j]
}
}
}
return(S)
}
Maybe you can add the S to the global environment with <<- and then run a loop:
Thermal<-function(S,t=0.000000000001,k=1){
#Defing beta
beta<-1/(k*t)
#multiplying each point of the array by all its adjacent points
#and summing them
Spointenergy<-S*((S2)+(S3)+S4+S5)
#Creating a loop over the whole array
for(i in 1:n){
for (j in 1:n){
#defining the change in energy at each point
dE<-energychange(S,i,j)
#By default each point does not flip
accept<-FALSE
#If energy decreases spin flip occurs 100% of the time
if (dE<0){
accept<-TRUE
}
#If energy increases a spin flip will occur if w is greater than or equal
#to u.
if (dE>=0){
w<-exp(-beta*dE)
u<-runif(1,0,1)
if (w>=u){
accept<-TRUE
}
}
#If no spin flip occurs there is no change in energy
if (accept==FALSE){
dE<-0
}
#if spin flip does occur then the magnitude of each lattice point is flipped
#from positive to negative or visa versa
if (accept==TRUE){
S[i,j]<--S[i,j]
}
}
}
return(S)
S<<-S
}
for (x in 1:10) {
Thermal(S)
}
S
Example with iris dataset:
> iris_num <- iris[,-5]
> head(iris_num)
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 5.1 3.5 1.4 0.2
2 4.9 3.0 1.4 0.2
3 4.7 3.2 1.3 0.2
4 4.6 3.1 1.5 0.2
5 5.0 3.6 1.4 0.2
6 5.4 3.9 1.7 0.4
>
> testfunction <- function(iris_num)
+ {
+ iris_num <<- iris_num + 1
+ }
>
> testfunction(iris_num)
> head(iris_num)
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 6.1 4.5 2.4 1.2
2 5.9 4.0 2.4 1.2
3 5.7 4.2 2.3 1.2
4 5.6 4.1 2.5 1.2
5 6.0 4.6 2.4 1.2
6 6.4 4.9 2.7 1.4
>
> for (x in 1:10) {
+ testfunction(iris_num)
+ }
>
> head(iris_num)
Sepal.Length Sepal.Width Petal.Length Petal.Width
1 16.1 14.5 12.4 11.2
2 15.9 14.0 12.4 11.2
3 15.7 14.2 12.3 11.2
4 15.6 14.1 12.5 11.2
5 16.0 14.6 12.4 11.2
6 16.4 14.9 12.7 11.4
>
Related
I'm a Julia beginner (scripting beginner too).
I have a text file which consists in 4 columns:
1 5.4 9.5 19.5
2 5.4 9.4 20.6
2 6.2 9.6 18.3
1 9.1 0.5 17.2
2 8.5 1.4 19.6
2 8.4 0.6 24.1
etc.
I have no idea how in Julia I can replace certain values in the rows or add a new one according to a existing column pattern 122 122. For example I would like to add the column with letter C and O (C when is 1 in the first column and O when is 2). I would like to add new column after the one with C and O where the pattern 1 2 2 is designated by number 4 and next by number 5. This is how I imagine the result:
C 4 1 5.4 9.5 19.5
O 4 2 5.4 9.4 20.6
O 4 2 6.2 9.6 18.3
C 5 1 9.1 0.5 17.2
O 5 2 8.5 1.4 19.6
O 5 2 8.4 0.6 24.1
Thank you for your help in advance.
Kasia.
String processing is fairly straightforward in Julia. You might write a function that takes an input and output filename as follows:
function munge_file(in::AbstractString, out::AbstractString)
# open the output file for writing
open(out, "w") do out_io
# open the input file for reading
open(in, "r") do in_io
# and process the contents
munge_file(in_io, out_io)
end
end
end
Now, the inner call to munge_file will have to do the actual work (this isn't particularly optimized, but should very straightforward):
function munge_file(input::IO, io::IO = IOBuffer())
# initialize the pattern index
pattern_index = 3
# iterate over each line of the input
for line in eachline(input)
# skip empty lines
isempty(line) && continue
# split the current line into parts
parts = split(line, ' ')
# this line doesn't conform to the specified input pattern
# might be better to throw an error here
length(parts) == 4 || continue
# this line starts a new pattern if the first character is a 1
is_start = parse(Int, parts[1]) == 1
# increment the counter (for the second output column)
pattern_index += is_start
# first column depends on whether a 1 2 2 pattern starts here or not
print(io, is_start ? 'C' : 'O')
print(io, ' ')
# print the pattern counter
print(io, pattern_index)
print(io, ' ')
# print the original line
println(io, line)
end
return io
end
Using the code in the REPL produces the expected output:
shell> cat input.txt
1 5.4 9.5 19.5
2 5.4 9.4 20.6
2 6.2 9.6 18.3
1 9.1 0.5 17.2
2 8.5 1.4 19.6
2 8.4 0.6 24.1
julia> munge_file("input.txt", "output.txt")
IOStream(<file output.txt>)
shell> cat output.txt
C 4 1 5.4 9.5 19.5
O 4 2 5.4 9.4 20.6
O 4 2 6.2 9.6 18.3
C 5 1 9.1 0.5 17.2
O 5 2 8.5 1.4 19.6
O 5 2 8.4 0.6 24.1
Assuming your file is input.txt you could do:
open("output.txt","w") do f
println.(Ref(f),replace.(replace.(readlines("input.txt"),r"^1 "=>"C "), r"^2 "=>"O "))
end;
Dots (.) in the above code vectorize it so functions work on vectors rather than scalars. The replace function takes a String, regular expression and new value. ^ in regular expression means "line starts with".
MATLAB software
i=[0 1.264241 1.729329 1.900426 1.963369 1.986524 1.995042 1.998176 1.999329 1.999753 1.999909];
t=[0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2];
How can I call the value of i if the user input is from the t array as the position for both array is the same?
For example, if I call the value 0.2 the program will call the value 1.264341 from array i.
You can use input to get the user to enter a number, and ismembertol to find the number's index in t. Once you have the index, you can get the corresponding value in i. You could even throw an error if the number entered is not found in t. Here's an example:
i=[0 1.264241 1.729329 1.900426 1.963369 1.986524 1.995042 1.998176 1.999329 1.999753 1.999909];
t=[0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2];
x = input('Enter number:\n');
[~,ind] = ismembertol(x,t);
if ind > 0
fprintf('Corresponding number in i is %g\n', i(ind))
else
error('Number not found in i')
end
I try to calculate a mean value of 10 matrix entries (1:10, 2:11, 3:12 and so on) and then make a new matrix out of these mean values. However, it always gives me Invalid Index.
A=rand(150,1);
number_of_rows=size(A,1);
for i=1:number_of_rows
B=mean(A(i:i+9,1),1);
C(i,:)=B;
end
The trivial following code does it, for any window's length n:
A = grand(1,40,"uin",0,9)
n = 10;
C = [0 cumsum(A)];
C = (C(n+1:$)-C(1:$-n))/n
Result (sample):
--> A = grand(1,40,"uin",0,9)
A =
column 1 to 24
3. 2. 2. 9. 2. 6. 1. 5. 1. 5. 7. 2. 5. 8. 3. 0. 3. 8. 3. 3. 4. 8. 8. 1.
column 25 to 40
4. 2. 0. 8. 5. 8. 5. 3. 7. 3. 1. 8. 8. 0. 0. 4.
--> n = 10;
--> C = [0 cumsum(A)];
--> C = (C(n+1:$)-C(1:$-n))/n
C =
column 1 to 20
3.6 4. 4. 4.3 4.2 4.3 3.7 3.9 4.2 4.4 4.2 3.9 4.5 4.8 4.1 4.2 4.4 4.1 4.1 4.3
column 21 to 31
4.8 4.9 4.4 4.3 4.5 4.2 4.8 5.6 4.8 4.3 3.9
--> mean(A(1:n))
ans =
3.6
However, cumsum() would propagate any Inf or NaN value belonging to A.
I was wondering how to go about adding or subtracting the first value of my data to/from the rest of the column, so that the first row of data would be 0.
For instance, this:
A = [13.2 12.4 -11.7 6.3 -4.0
14.2 13.1 -9.2 8.2 -4.1
14.4 14.5 -7.6 10.0 -5.1];
Would change to:
0 0 0 0 0
1 0.7 2.5 1.9 0.1
1.2 2.1 4.1 3.7 1.1
I think I can check whether the first number is positive/negative by using sign() and choose whether to add or subtract this using an ifelse statement, but I am unsure how to apply this to each column individually (or if this is the best way!).
Many thanks in advance.
You actually need element-by-element operation, as the definition of bsxfun states. In your case it should be:
A = [13.2 12.4 -11.7 6.3 -4.0
14.2 13.1 -9.2 8.2 -4.1
14.4 14.5 -7.6 10.0 -5.1];
B=bsxfun(#minus,A,A(1,:))
B =
0 0 0 0 0
1.0000 0.7000 2.5000 1.9000 -0.1000
1.2000 2.1000 4.1000 3.7000 -1.1000
This is the result for your question description, but for the example that you add, I assume that you want the absolute values, so you need to add abs:
B=abs(bsxfun(#minus,A,A(1,:)))
B =
0 0 0 0 0
1.0000 0.7000 2.5000 1.9000 0.1000
1.2000 2.1000 4.1000 3.7000 1.1000
You can select the first row and subtract it from the matrix.
A = A - A(1, :)
Or for older versions of Matlab:
A = A - repmat(A(1, :), size(A, 1), 1)
I have a sorted (Ascending trend) array as
[1 1 1 1 1 1.2 1.6 2 2 2 2.4 2.4 2.4 2.6 3 3.5 3.6 3.8 3.9 4 4.3 4.3 4.6 5 5.02 6 7]
I want to check and print the number of the repeated numbers between each "natural numbers".
for example:
between 1 and 2: 0 (no repeated)
between 2 and 3: 3 repeated with 2.4
between 3 and 4: 0
between 4 and 5: 2 repeated with 4.3
between 5 and 6: 0
between 6 and 7: 0
Is there any function in MATLAB to do this task?
you can use tabulate, and the array need not be even sorted for that.
Then just select the proper elements using logical conditions. For example:
A=[1 1 1 1 1 1.2 1.6 2 2 2 2.4 2.4 2.4 2.6 3 3.5 3.6 3.8 3.9 4 4.3 4.3 4.6 5 5.02 6 7]
M=tabulate(A) % get frequency table
id1=mod(M(:,1),1)>0; % get indices for non integer values
id2=M(:,2)>1; % get indices for more than one occurrence
idx=id1 & id2; % get indices that combines the two above
ans=[M(idx,1) , M(idx,2)] % show value , # of repeats
ans =
2.4000 3.0000
4.3000 2.0000
the alternative is to use histc. So if your vector is stored in a then
h = histc(a,a); % count how many times the number is there, the a should be sorted
natNumbers = (mod(a,1)==0) .* h;
nonnatNum = (mod(a,1)>0).*h;
indNN = find(natNumbers>0);
indNNN = find(nonNatNumbers>1);
resultIndex = sort([indNN indNNN]);
result = [a(resultIndex);h(resultIndex)]
Then you can work with the result matrix by checking if there are any numbers between natural numbers