I am looking for the best way to adjust the same field, y, of an array of mutable structs, x to the same number.
x[:].y=0 kind of thing. In matlab I've seen it done using the deal() function. How can I do this in Julia?
You can use broadcasting:
setproperty!.(x, :y, 0)
Don't be afraid of writing the most obvious thing: a loop! It will be efficient in Julia. For example something like
for el in x
el.y = 0
end
Related
I'm formatting f64 like this:
format!("{:.8}", x)
This returns strings like this:
110.00000000
601.47000000
4.50000000
I'm looking to remove all the extra zeros at the end of each so that the output is this:
110
601.47
4.5
I'm hoping to do this without any external crates or libraries (not a big deal if it has to happen though). Is there something built-in to Rust that can accomplish this? Or will I have to write a custom function to do so?
Edit:
I should add that I can't simple do format("{}", x) because that will return strings like this:
40.019999999999996
1192.6499999999999
2733.9599999999996
Is there a way around that?
This currently solves the issue for me:
let y = (x * 100_000_000.0).round() / 100_000_000.0;
format!("{}", y);
I will keep an eye out for any better solutions. Thank you!
You can just do
format!("{}", x)
The {:.8} requires 8 places of precision, and thus, prints out extra zeros to that precision.
I have an immutable structure with four objects defined as follows:
struct FltFric
muS::Array{Float64, 2}
muD::Array{Float64, 2}
Dc::Float64
W::Array{Float64, 2}
end
muS = repmat([0.6], 100, 1) # Coefficient of static friction
muD = repmat([0.5], 100, 1) # Coefficient of dynamic friction
Dc = 0.1 # Critical slip distance
FltFriction = FltFric(muS, muD, Dc, zeros(size(muS)))
I am modifying the values of FltFric.muS as follows:
FltFriction.muS[1:20] = 100
This works fine. But when I try to modify the value of W
FltFriction.W = (FltFriction.muS - FltFriction.muD)./(FltFriction.Dc)
This gives me an error: type FltFric is immutable.
Why does the first statement not give error while the second one does? If the type is immutable, both statements should give an error. What is the difference between the two assignments?
I know that I can circumvent the problem by typing mutable struct, but I don't understand the difference in my two assignments.
I am not a Julia expert, but I think this is a more general question.
In the first assignment, you're modifying certain elements of the list FltFriction.muS. This is fine since although the struct is immutable, the list referred to by .muS is mutable. In other words, you're mutating the list by changing its elements, rather than mutating the struct.
In the second assignment, you're trying to replace the entire list .W in one fell swoop. In this case you're trying to mutate the struct directly, replacing one of its elements. For this reason, the second assignment fails while the first one succeeds.
I'm speculating here, but I suspect that if you tried to do the second assignment like so:
FltFriction.W[1:end] = ...
Then you would be fine, since you're mutating the list instead of the struct.
As pointed out by a commenter (see below), in Julia there is a "more idiomatic (and more performant)" way to do this correctly and without mutating the struct itself by using the in-place assignment operator (neat!):
FltFriction.W .= (FltFriction.muS - FltFriction.muD)./FltFriction.Dc
So I'm playing with Sympy in an effort to build a generic solver/generator of physics problems. One component is that I'm going for a function that will take kwargs and, according to what it got, rearrange the equation and substitute values in it. Thanks to SO, I managed to find the things I need for that.
However..... I've tried putting sympy.solve in a for loop to generate all those expressions and I've ran into.... something.
import sympy
R, U, I, eq = sympy.symbols('R U I eq')
eq = R - U/I
for x in 'RUI':
print(x)
print(sympy.solve(eq, x))
The output?
R
[U/I]
U
[I*R]
I
[]
However, whenever I do sympy.solve(eq, I) it works and returns [U/R].
Now, I'm guessing the issue is with sympy using I for imaginary unit and with variable hiding in blocks, but even when I transfer the symbol declaration inside the for loop (and equation as well), I still get the same problem.
I'm not sure I'll need this badly in the end, but this is interesting to say the least.
It's more like an undocumented feature than a bug. The loop for x in 'RUI' is equivalent to for x in ['R', 'U', 'I'], meaning that x runs over one-character strings, not sympy symbols. Insert print(type(x)) in the loop to see this. And note that sympy.solve(eq, 'I') returns [].
The loop for x in [R, U, I] solves correctly for each variable. This is the right way to write this loop.
The surprising thing is that you get anything at all when passing a string as the second argument of solve. Sympy documentation does not list strings among acceptable arguments. Apparently, it tries to coerce the string to a sympy object and does not always guess your meaning correctly: works with sympy.solve(eq, 'R') but not with sympy.solve(eq, 'I')
The issue is that some sympy functions "accidentally" work with strings as input because they call sympify on their input. But sympify('I') gives the imaginary unit (sqrt(-1)), not Symbol('I').
You should always define your symbols explicitly like
R, U, I = symbols("R U I")
and use those instead of strings.
See https://github.com/sympy/sympy/wiki/Idioms-and-Antipatterns#strings-as-input for more information on why you should avoid using strings with SymPy.
I have an ODE that uses many functions. I wish to export these "helper" functions so that I may graph them vs the independent variable of the ODE.
function dFfuncvecdW = ODE(W,Ffuncvec);
X = Ffuncvec(1);
y = Ffuncvec(2);
#lots of code
R = ... #R is a function of X,W and y.
#and a few other functions that are a function of X,W and y.
dXdW = ... #some formula
dydW = ... #some formula
dFfuncvecdW = [dXdW; dydW];
end
I call this function with:
Wspan = [0 8000.]
X0 = [0; 1.]
[W,X] = ode45(#ODE, Wspan, X0);
I can easily output X or W to an excel file:
xlswrite(filename,X,'Conversion','A1');
But I what I need is to save "R" and many other functions' values to an Excel file.
How do I do that?
I am still extremely new to Matlab. I usually use Polymath, but for this system of ODE's, Polymath cannot compute the answer within a reasonable amount of time.
EDIT1: The code I use was generated by Polymath. I used a basic version of my problem so that Polymath may excecute the program as it only gives the Matlab code once the Polymath code has succefully run. After the export, the complete set of equations were entered.
The easiest, and possibly fastest, way to handle this is to re-evaluate your functions after ode45 returns W and X. If the functions are vectorized it will be easy. Otherwise, just use a simple for loop that iterates from 1 to length(W).
Alternatively, you can use an output function to save your values on each iteration to a file, or a global, or, most efficiently, a sub-function (a.k.a. nested function) variable that shares scope with an outer function (see here, for example). See this answer of mine for an example of how to use an output function.
I found a rather quick and painless solution to my answer.
I merely appended a text file with code inside the ode function.
EDIT: I am unable to comment because I do have enough rep on this branch of SE.
My solution was add the following code:
fid = fopen('abc1.txt', 'at');
fprintf(fid, '%f\n', T);
fclose(fid);
right above
dYfuncvecdW = [dFAdW; dFBdW; dFCdW; dFDdW; dydW];
at the end of the ode function. This proved to be a temporary solution. I have opened another question about the output I recieved.
I am trying to produce the argument string for an anonymous function based on the number of input arguments without using for loops. For example, if N=3, then I want a string that reads
#(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))
I tried using repmat('ax',1,N) but I cannot figure out how to interleave the (i) index.
Any ideas?
Aside: Great answers so far, the above problem has been solved. To provide some intuition for those who are wondering why I want to do this: I need to construct a very large matrix anonymous function (a Jacobian) on the order of 3000x3000. I initially used the Matlab operations jacobian and matlabFunction to construct the anonymous function; however, this was quite slow. Instead, since the closed form of the derivative was quite simple, I decided to form the anonymous function directly. This was done by forming the symbolic Jacobian matrix, J, then appending it to the above #() string by using char(J{:})' and using eval to form the final anonymous function. This may not be the most elegant solution but I find it runs much faster than the jacobian/matlabFunction combination, especially for large N (additionally the structure of the new approach allows for the evaluation to be done in parallel).
EDIT: Just for completeness, the correct form of the argument string for the anonymous function should read
#(ax1,ax2,ax3,ay1,ay2,ay3)
to avoid a syntax error associated with indexing.
I suggest the following:
N = 3;
argumentString = [repmat('ax(%i),',1,N),repmat('ay(%i),',1,N)];
functionString = sprintf(['#(',argumentString(1:end-1),')'], 1:N, 1:N)
First, you create input masks for sprintf (e.g. 'ax(%i)'), which you then fill in with the appropriate numbers to create the function string.
Note: the syntax #(ax(1),...) will not actually work. More likely, you want to use either #()someFunction(ax(1),...), or you are trying to pass multiple input arguments to an existing function, in which case storing the inputs in a cell array and calling the function as fun(axCell{:}) would work.
A solution would be to use arrayfun:
sx = strjoin(arrayfun(#(x) ['ax(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
sy = strjoin(arrayfun(#(x) ['ay(' num2str(x) ')'], 1:3, 'UniformOutput', false), ',');
s = ['#(' sx ',' sy ')'];
contains
'#(ax(1),ax(2),ax(3),ay(1),ay(2),ay(3))'
Best,
Try this:
N = 3;
sx = strcat('ax(', arrayfun(#num2str, 1:N, 'uniformoutput', 0), '),');
sy = strcat('ay(', arrayfun(#num2str, 1:N, 'uniformoutput', 0), '),');
str = [sx{:} sy{:}];
str = ['#(' str(1:end-1) ')']