Check multiple conditions on the same function output in Julia - julia

Is there a way to check multiple Boolean conditions against a value (to achieve the same as below) without computing sum twice or saving the result to a variable?
if sum(x) == 1 || sum(x) > 3
# Do Something
end

You can use one of several options:
Anonymous function:
if (i->i>3||i==1)(sum(x))
# Do Something
end
Or,
if sum(x) |> i->i>3||i==1
# Do Something
end
DeMorgan's theorem:
if !(3 >= sum(x) != 1)
# Do Something
end
And if used inside a loop:
3 >= sum(x) != 1 && break
# Do Something
or as function return:
3 >= sum(x) != 1 && return false
But using a temporary variable would be the most readable of all:
s = sum(x)
if s > 3 || s == 1
# Do Something
end

Syntactically, a let is valid in that position, and the closest equivalent to AboAmmar's variant with a lambda:
if let s = sum(x)
s == 1 || s > 3
end
# do something
end
I'd consider this rather unidiomatic, though.

Related

sum function in Julia is giving error if the array is empty

I am trying to create a code which identifies if the elements in an array are monotonic or not.
I wrote the below code and got the error -
function isMonotonic(array)
if length(array) <= 2
return true
end
check_up = []
check_down = []
for i in range(2, length(array))
if array[i] <= array[i-1]
append!(check_up, 1)
end
if array[i] >= array[i - 1]
append!(check_down, 1)
end
end
if sum(check_up) == length(array) - 1 || sum(check_down) == length(array) - 1
return true
else
return false
end
end
isMonotonic([1, 2, 3, 4, 5, 6 , 7])
I am getting the below error
Error: Methoderror: no method matching zero(::Type{Any})
I think it is because I am trying to sum up the empth array, I want to understand how to overcome this problem in general, I have a solution for the above code, but in genral I want to know the reason and how to use it. I do not want to first check if the array is empty or not and then do the sum.
If you wanted to save yourself lots of effort, the simplest solution would just be:
my_ismonotonic(x) = issorted(x) || issorted(x ; rev=true)
This will return true if x is sorted either forwards, or in reverse, and false otherwise.
We could maybe make it a little more efficient using a check so we only need a single call to issorted.
function my_ismonotonic(x)
length(x) <= 2 && return true
for n = 2:length(x)
if x[n] > x[1]
return issorted(x)
elseif x[n] < x[1]
return issorted(x ; rev=true)
end
end
return true
end
# Alternatively, a neater version using findfirst
function my_ismonotonic(x)
length(x) <= 2 && return true
ii = findfirst(a -> a != x[1], x)
isnothing(ii) && return true # All elements in x are equal
if x[ii] > x[1]
return issorted(x)
else
return issorted(x ; rev=true)
end
end
The loop detects the first occurrence of an element greater than or less than the first element and then calls the appropriate issorted as soon as this occurs. If all elements in the array are equal then the loop runs over the whole array and returns true.
There are a few problems of efficiency in your approach, but the reason you are getting an actual error message is because given the input, either this expression sum(check_up) or this expression sum(check_down) will effectively result in the following call:
sum(Any[])
There is no obvious return value for this since the array could have any type, so instead you get an error. If you had used the following earlier in your function:
check_up = Int[]
check_down = Int[]
then you shouldn't have the same problem, because:
julia> sum(Int[])
0
Note also that append! is usually for appending a vector to a vector. If you just want to add a single element to a vector use push!.

Conditional statements in Julia

I define two non-empty vectors:
tmp = [1, 2, 3]
tmp2 = [1, 2]
When I type
size(tmp, 1) > 0
The output is true. But when I write
size(tmp, 1) > 0 & size(tmp2, 1) > 0
it returns false.
When I put each term into a parentheses, as in
(size(tmp, 1) > 0) & (size(tmp2, 1) > 0 )
it returns true as expected. But I don't understand why size(tmp, 1) > 0 & size(tmp2, 1) > 0 returns false?
This is a result of 2 things. The first is operator precedence. The code you wrote is parsed as size(tmp, 1) > (0 & size(tmp2, 1)) > 0 (ie as a chained comparison).
The bigger issue, however is that you probably wanted to use && instead of &. & is a bitwise and, while && is a logical and. As such, && has the precedence you expect here.

Julia way of searching tokens in integer arrays

Let's say I have buffer=Int[1,2,3,2,3] and token=[2,3].
Is there any preferred way of searching the occurrence of token in buffer to find [2,4] as the answer.
Or, perhaps, is there any split equivalent function for the integer arrays in julia?
(I know how I can perform this operation using 2 nested loops. However, I am especially interested if there is a more Julian way of doing this.)
Because Julia doesn't have conditionals in list comprehensions, I would personally use filter(). Thus if arr = Int64[1,2,3,4,5,2,3,6,2,3,3,2,2]:
filter(x -> arr[x] == 2 && arr[x + 1] == 3, 1 : length(arr) - 1)
=> [2,6,9]
To make it a little more reusable:
pat = [2,3]
filter(x -> arr[x : x + length(pat) - 1] == pat, 1 : length(arr) - length(pat) + 1)
=> [2,6,9]
Julia does have built-ins like find([fun], A), but there's no way that I'm aware of to use them to return indexes of an ordered sublist.
Of course it's arguably more legible to just
ndxs = Int64[]
for i = 1:length(arr)-1
if arr[i] == 2 && arr[i+1] == 3
push!(ndxs, i)
end
end
=> [2,6,9]
For practice I have also made trial-and-errors and the following patterns have worked for Julia0.4.0. With A = Int[1,2,3,2,3] and pat = Int[2,3], the first one is
x = Int[ A[i:i+1] == pat ? i : 0 for i=1:length(A)-1 ]
x[ x .> 0 ] # => [2,4]
the second one is
x = Int[]
[ A[i:i+1] == pat ? push!(x,i) : 0 for i=1:length(A)-1 ]
#show x # => [2,4]
and the third one is
find( [ A[i:i+1] == pat for i=1:length(A)-1 ] ) # => [2,4]
(where find() returns the index array of true elements). But personally, I feel these patterns are more like python than julia way...

What does "&&" do?

I can't seem to find the resource I need. What does && do in a code that is comparing variables to determine if they are true? If there is a link with a list of the symbol comparisons that would be greatly appreciated.
example: Expresssion 1: r = !z && (x % 2);
In most programming languages that use &&, it's the boolean "and" operator. For example, the pseudocode if (x && y) means "if x is true and y is true."
In the example you gave, it's not clear what language you're using, but
r = !z && (x % 2);
probably means this:
r = (not z) and (x mod 2)
= (z is not true) and (x mod 2 is true)
= (z is not true) and (x mod 2 is not zero)
= (z is not true) and (x is odd)
In most programming languages, the operator && is the logical AND operator. It connects to boolean expressions and returns true only when both sides are true.
Here is an example:
int var1 = 0;
int var2 = 1;
if (var1 == 0 && var2 == 0) {
// This won't get executed.
} else if (var1 == 0 && var2 == 1) {
// This piece will, however.
}
Although var1 == 0 evaluates to true, var2 is not equals to 0. Therefore, because we are using the && operator, the program won't go inside the first block.
Another operator you will see ofter is || representing the OR. It will evaluate true if at least one of the two statements are true. In the code example from above, using the OR operator would look like this:
int var1 = 0;
int var2 = 1;
if (var1 == 0 || var2 == 0) {
// This will get executed.
}
I hope you now understand what these do and how to use them!
PS: Some languages have the same functionality, but are using other keywords. Python, e.g. has the keyword and instead of &&.
It is the logical AND operator
(&&) returns the boolean value true if both operands are true and returns false otherwise.
boolean a=true;
boolean b=true;
if(a && b){
System.out.println("Both are true"); // Both condition are satisfied
}
Output
Both are true
The exact answer to your question depends on the which language your are coding in. In R, the & operator does the AND operation pairwise over two vectors, as in:
c(T,F,T,F) & c(T,T,F,F)
#> TRUE FALSE FALSE FALSE
whereas the && operator operated only on the first element of each vector, as in:
c(T,F,T,F) && c(T,T,F,F)
#> TRUE
The OR operators (| and ||) behave similarly. Different languages will have different meanings for these operators.
In C && works like a logical and, but it only operates on bool types which are true unless they are 0.
In contrast, & is a bitwise and, which returns the bits that are the same.
Ie. 1 && 2 and 1 && 3 are true.
But 1 & 2 is false and 1 & 3 is true.
Let's imagine the situation:
a = 1
b = 2
if a = 1 && b = 2
return "a is 1 and b is 2"
if a = 1 && b = 3
return "a is 1 and b is 3"
In this situation, because a equals 1 AND b = 2, the top if block would return true and "a is 1 and b is 2" would be printed. However, in the second if block, a = 1, but b does not equal 3, so because only one statement is true, the second result would not be printed. && Is the exact same as just saying and, "if a is 1 and b is 1".

What functions work with JuMPArrays?

Is there a way to make certain functions such as isinteger() work with JuMPArrays?
I am using Julia/JuMP to solve an optimization problem, and after I get the solution, I want to check if the solution is integer. So here is what I wrote:
#defVar(m, 0<= x[1:3] <= 1)
...
xstar = getValue(x)
if isinteger(xstar)
...
end
And I get an error saying isinteger() has no method matching isinteger(::JuMPArray).
Thanks
So in general you can get an underlying array from a JuMPArray by using [:], e.g.
m = Model()
#variable(m, 0 <= x[1:3] <= 1)
#variable(m, 0 <= y[1:10, 1:10] <= 1)
solve(m)
xstar = getvalue(x)[:]
ystar = getvalue(y)[:,:]
Note that the reason for this is that JuMPArrays don't have to start with index 1, so the user needs to explicitly say they want a normal Julia array before doing things.
Regardless, you shouldn't use isinteger. Solvers don't always return very precise answers, e.g. they might say x[1] = 0.999996 but they really mean it is 1. You should do something like
for i in 1:3
if getvalue(x[i]) >= 0.999
println("x[$i] is 1!")
elseif getvalue(x[i]) <= 0.001
println("x[$i] is 0!")
end
end
to make sure you don't get any false negatives. If the variable is restricted to be integer or binary, use iround, e.g.
for i in 1:3
v = iround(getvalue(x[i]))
if v == 1
println("x[$i] is 1!")
elseif v == 0
println("x[$i] is 0!")
end
end
but it looks like in this case you are just seeing if the solution is naturally 0 or 1.

Resources