How to assign equation-expression to variable then sent to solve()? - sage

I am using both SageMath and Wolfram Alpha to entertain myself over the weekend.
I found this SageMath demo of solving simultaneous equations:
var('x y p q')
eq1 = p+q==9
eq2 = q*y+p*x==-6
eq3 = q*y^2+p*x^2==24
solve([eq1,eq2,eq3,p==1],p,q,x,y)
And it gave me this result:
[
[ p == 1
, q == 8
, x == -4/3*sqrt(10) - 2/3
, y == 1/6*sqrt(10) - 2/3
]
,[p == 1
, q == 8
, x == 4/3*sqrt(10) - 2/3
, y == -1/6*sqrt(10) - 2/3
]
]
I tried this syntax on Alpha:
solve p+q==9 , q*y+p*x==-6 , q*y^2+p*x^2==24 , p==1
It works well.
Question:
How to operate Alpha so I assign each equation to a variable and then supply that variable to solve as a parameter?
I want to simplify my call to solve() so it looks like this:
solve eq1, eq2, eq3, p==1
instead of this:
solve p+q==9 , q*y+p*x==-6 , q*y^2+p*x^2==24 , p==1

So, Crazy Ivan's comment really answers this. WolframAlpha is not a programming language. It is a glorified online smart calculator. You can only do very limited computations in it. Check out the Wolfram Language for the full-fledged programming language.

Related

Second order delay differential equation in Julia

I'm new to Julia programming I managed to solve some 1st order DDE (Delay Differential Equations) and ODE. I now need to solve a second order delay differential equation but I didn't manage to find documentation about that (I previously used DifferentialEquations.jl).
The equation (where F is a function and τ the delay):
How can I do this?
Here is my code using the given information, it seems that the system stay at rest which is incorrect. I probably did something wrong.
function bc_model(du,u,h,p,t)
# [ u'(t), u''(t) ] = [ u[1], -u[1] + F(ud[0],u[0]) ] // off by one in julia A[0] -> A[1]
γ,σ,Q = p
ud = h(p, t-σ)[1]
du = [u[2], + Q^2*(γ/Q*tanh(ud)-u[1]) - u[2]]
end
u0 = [0.1, 0]
h(p, t) = u0
lags = [σ,0]
tspan = (0.0,σ*100.0)
alg = MethodOfSteps(Tsit5())
p = (γ,σ,Q,ω0)
prob = DDEProblem(bc_model,u0,h,tspan,p; constant_lags=lags)
sol = solve(prob,alg)
plot(sol)
The code is in fact working! It seems that it is my normalization constants that are not consistent. Thank you!
You get a state space of dimension 2, containing u = [u(t),u'(t)]. Consequently the return vector of the right-side function is [u'(t),u''(t)]. Then if ud is the delayed state [u(t-τ),u'(t-τ)] the right side function can be formulated as
[ u'(t), u''(t) ] = [ u[1], -u[1] + F(ud[0],u[0]) ]

How to use NLopt in Julia with equality_constraint

I'm struggling to amend the Julia-specific tutorial on NLopt to meet my needs and would be grateful if someone could explain what I'm doing wrong or failing to understand.
I wish to:
Minimise the value of some objective function myfunc(x); where
x must lie in the unit hypercube (just 2 dimensions in the example below); and
the sum of the elements of x must be one.
Below I make myfunc very simple - the square of the distance from x to [2.0, 0.0] so that the obvious correct solution to the problem is x = [1.0,0.0] for which myfunc(x) = 1.0. I have also added println statements so that I can see what the solver is doing.
testNLopt = function()
origin = [2.0,0.0]
n = length(origin)
#Returns square of the distance between x and "origin", and amends grad in-place
myfunc = function(x::Vector{Float64}, grad::Vector{Float64})
if length(grad) > 0
grad = 2 .* (x .- origin)
end
xOut = sum((x .- origin).^2)
println("myfunc: x = $x; myfunc(x) = $xOut; ∂myfunc/∂x = $grad")
return(xOut)
end
#Constrain the sums of the x's to be 1...
sumconstraint =function(x::Vector{Float64}, grad::Vector{Float64})
if length(grad) > 0
grad = ones(length(x))
end
xOut = sum(x) - 1
println("sumconstraint: x = $x; constraint = $xOut; ∂constraint/∂x = $grad")
return(xOut)
end
opt = Opt(:LD_SLSQP,n)
lower_bounds!(opt, zeros(n))
upper_bounds!(opt,ones(n))
equality_constraint!(opt,sumconstraint,0)
#xtol_rel!(opt,1e-4)
xtol_abs!(opt,1e-8)
min_objective!(opt, myfunc)
maxeval!(opt,20)#to ensure code always terminates, remove this line when code working correctly?
optimize(opt,ones(n)./n)
end
I have read this similar question and documentation here and here, but still can't figure out what's wrong. Worryingly, each time I run testNLopt I see different behaviour, as in this screenshot including occasions when the solver uselessly evaluates myfunc([NaN,NaN]) many times.
You aren't actually writing to the grad parameters in-place, as you write in the comments;
grad = 2 .* (x .- origin)
just overrides the local variable, not the array contents -- and I guess that's why you see these df/dx = [NaN, NaN] everywhere. The simplest way to fix that would be with broadcasting assignment (note the dot):
grad .= 2 .* (x .- origin)
and so on. You can read about that behaviour here and here.

Using solve and/or linsolve with the symbolic toolbox in R2010b

I asked a question a few days ago here and got an answer that seems like it would work- it involves using linsolve to find the solutions to a system of equations that are all modulo p, where p is a non-prime integer.
However, when I try to run the commands from the provided answer, or the linsolve help page, I get an error saying linsolve doesn't support arguments of type 'sym'. Is using linsolve with sym variables only possible in R2013b? I've also tried it with my school's copy, which is R2012b. Here is the code I'm attempting to execute (from the answer at the above link):
A = [0 5 4 1;1 7 0 2;8 1 0 2;10 5 1 0];
b = [2946321;5851213;2563617;10670279];
s = mod(linsolve(sym(A),sym(b)),8)
And the output is:
??? Undefined function or method linsolve' for input arguments of type 'sym'.
I've also tried to use the function solve for this, however even if I construct the equations represented by the matrices A and b above, I'm having issues. Here's what I'm attempting:
syms x y z q;
solve(5*y + 4*z + q == 2946321, x + 7*y + 2*q == 5851213, 8*x + y + 2*q == 2563617, 10*x + 5*y + z == 10670279,x,y,z,q)
And the output is:
??? Error using ==> char
Conversion to char from logical is not possible.
Error in ==> solve>getEqns at 169
vc = char(v);
Error in ==> solve at 67
[eqns,vars] = getEqns(varargin{:});
Am I using solve wrong? Should I just try to execute my code in R2013b to use linsolve with symbolic data types?
The Symbolic Math toolbox math toolbox has changed a lot (for the better) over the years. You might not have sym/linsolve, but does this work?:
s = mod(sym(A)\sym(b),8)
That will basically do the same thing. sym/linsolve just does some extra input checking and and rank calculation to mirror the capabilities of linsolve.
You're using solve correctly for current versions, but it looks like R2010b may not understand the == operator (sym/eq) in this context. You can use the old string format to specify your equations:
eqs = {'5*y + 4*z + q = 2946321',...
'x + 7*y + 2*q = 5851213',...
'8*x + y + 2*q = 2563617',...
'10*x + 5*y + z = 10670279'};
vars = {'x','y','z','q'};
[x,y,z,q] = solve(eqs{:},vars{:})

How to get equivalent to R ifelse functionality, using logical operators

Please can anyone advise how I can turn the following statement into one that will do the same thing but NOT using ifelse please?
<-ifelse(y>=50, 0.2*x+0.8*y, ifelse(y<50 & x>70, y+10, ifelse(y<50 & x<70, y)))
x=80
y=60
So I the final code should give an answer of 64 - selecting the first condition. I will then test it to ensure the other 3 conditions give the correct result for varying values of x and y
Thanks a lot.
This should work:
finalmark <- (x * 0.2 + y * 0.8) * (y >= 50) + (y + 10 * (x > 70)) * (y < 50)
Something like this?
if(y>=50){
0.2*x+0.8*y
}else{
if(y<50 & x>70){
y+10
}else{
if(y<50 & x<70){
y
}else{
"OMG I did not expect this scenario"
}
}
}
try: y=45; x=70 to see why I have the last condition.
If y is a number then, once you've tested for y > = 50 then y must be less than 50 so don't keep testing for that. Similarly, once you've found x > 70 then you don't need the last ifelse. You don't have a return for x = 70. My guess is that you want to test for a <= or >= situation there.
ifelse(y>=50, 0.2*x+0.8*y, ifelse(x>70, y+10, y))
in scalar that's
if(y >= 50){
0.2*x+0.8*y
}else if(x > 70){
y+10
}else y
Given you seem to be having a hard time in general writing the logic I suggest you post a more complete question. It's possible (probable) that you're doing something here that you really don't want to do.
There are several approaches you can take. Below are a few examples of building a function 'f', so that 'f(x,y)' meets your criteria listed in the question using logic other than 'ifelse' statements.
Note: I'm also adding in one amendment to the original post, since 'x=70' would break the logic. I'm adding 'x>=70' to the second criterion.
Option 1: Use a standard 'if / else if / else' logic block. Personally, I like this option, because it's easily readable.
f <- function(x, y){
if (y>= 50){
return(0.2*x+0.8*y)
} else if (y < 50 & x >= 70){
return(y+10)
} else {
return(y)
}
}
Option 2: Combine your two logical tests (there are really only two) into a string, and use a switch. Note that the final and unnamed option is treated as an 'else'.
f <- function(x, y){
return(
switch(paste(x >= 70, y >= 50, sep=""),
TRUEFALSE = y + 10,
FALSEFALSE = y,
0.2*x+0.8*y
)
)
}
Option 3: Order your 'if' statements to reduce logical comparisons. This is the sort of thing to do if you have a large data set or very limited memory. This is slightly harder to troubleshoot, since you have to read the whole block to fully understand it. Option 1 is better if you don't have memory or cycle limitations.
f <- function(x, y){
if (y >= 50){
return(0.2*x+0.8*y)
} else {
if (x >=70){
return(y+10)
} else {
return(y)
}
}
}
There are other options, but these are the simplest that come readily to mind.

using while loop with logical operators (AND and OR)

n<-NULL
acr<-NULL
while((is.numeric(n)==F) & (acr<0 ¦acr>1)){
print("enter a positive integer and the average cancellation rate you want")
try(n<-scan(what=integer(),nmax=1), silent=TRUE);
try(acr<-scan(what=double(),nmax=1), silent=TRUE)
}
I would want the users of my program to enter a positive integer which I store in "n" and the second
entry which I keep in "acr" is a probability so it lies between 0 and 1.
(I don't want it to be exacly 0 or 1, though it could be according to probability theory).
So I want the user to keep on doing the entry until they are able to enter a positive integer for "n" and a probability value between 0 and 1 for "acr".(using while with the AND, OR operators)
However, I am having a problem with the while statement/loop. I have tried all other possibilities such as the one below, but it still doesn't work.
while(is.numeric(n)==F & acr<0 ¦acr>1)
AGAIN:question 2
There is a problem with what=double() also in the scan function, I think.
I know that, for example, 0.5 is a double data type in other programming languages but
I cannot figure it out in R(I don't know what it is called in R).
what is the difference between integer() and double() in R? (I am not familiar with double)
I would be highly appreciative to anyone who could come to my aid.
many thanks to all.
Isaac Owusu
This following example should work. Please be aware that is.integer()
"does not test if ‘x’ contains
integer numbers! For that, use
‘round’, as in the function
‘is.wholenumber(x)’ in the examples"
(see help(is.integer)).
For that reason, I first define a new function is.wholenumber().
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5){
abs(x - round(x)) < tol
}
n <- NULL
acr <- NULL
stay.in.loop <- TRUE
while(stay.in.loop){
print("Please insert n and acr!")
n <- readline("Insert n: ")
acr <- readline("Insert acr: ")
n <- as.numeric(n)
acr <- as.numeric(acr)
## stay.in.loop is true IF any of the expressions is NOT TRUE
stay.in.loop <- !(is.wholenumber(n) & ((0 < acr) & (acr < 1)))
}
NULL may be a bad initialization here, as its comparison does not give a regular boolean. Since the condition is that n should be positive, try this:
n <- -2
acr <- -2
while((n<=0) | (acr<0) | (acr>1)) {
print("enter a positive integer and the average cancellation rate you want")
try(n<-scan(what=integer(),nmax=1), silent=TRUE);
try(acr<-scan(what=double(),nmax=1), silent=TRUE);
}

Resources