Julia plots log axis: change powers (-1, 0, 1) of 10 (only) by: (0.1, 1, 10) labels - julia

I hate those (semi/log-)log plots with: 10^⁻1, 10⁰ and 10¹ labels.
A good way to change only these by, simply: 0.1, 1, and 10 please?
plot(x, y, yscale=:log10, label="", yformatter = yi -> yi==0.1 ? "0.1" : yi==1 ? "1" : yi==10 ? "10" : yi)
does part of the job, but how to keep the default 10^p format for |p|>1, please?

You could write something like:
function yformatter(yi)
yi < 1.0 && return string(yi)
yi <= 10 && return string(round(Int,yi))
nums = [['¹','²','³'] ; '⁴':'⁹']
return "10$(nums[round(Int,log10(yi))])"
end
And now you have:
julia> yformatter.([0.1, 1, 10, 100, 1_000, 10_000, 100_000])
7-element Vector{String}:
"0.1"
"1"
"10"
"10²"
"10³"
"10⁴"
"10⁵"

Related

How to limit digits in 9 by 9 matrix Julia

How can I limit the digits of data matrix to 2 digits?
data = reshape([tuple(c[i], c2[i]) for i in eachindex(c, c2)], 9, 9)
#9×9 Matrix{Tuple{Real, Real}}:
hl = Highlighter((d,i,j)->d[i,j][1]*d[i,j][2] < 0, crayon"red")
pretty_table(data ; header = names, row_names= names , highlighters=hl)
There are a couple of ways to do this:
You can use the round function:
data = round(data, 2)
You can use string formatting:
data = ["{0:.2f}".format(x) for x in data]
You can round the numbers when creating the data variable:
round2(n) = round(n; digits = 2)
data = reshape([tuple(round2(c[i]), round2(c2[i])) for i in eachindex(c, c2)], 9, 9)
Or if you want to maintain precision in the data array, but limit to 2 digits just for the printing, you can use the formatters keyword argument of PrettyTables:
pretty_table(data; header = titles, row_names = titles, formatters = (v, i, j) -> round.(v; digits = 2))
You can use an anonymous function as a formatter, like this:
formatter = (v, i, j) -> round(v, digits=2);
hl = Highlighter((d,i,j)->di,j*d[i,j][2] < 0, crayon"red")
pretty_table(data; header=names, row_names=names , highlighters=hl, formatters=formatter)
I encourage you to read the documentations for further options.
I understand you have a matrix of tuples such as:
julia> mx = [tuple(rand(2)...) for i in 1:3, j=1:2]
3×2 Matrix{Tuple{Float64, Float64}}:
(0.617653, 0.0742714) (0.0824311, 0.0344668)
(0.327074, 0.235599) (0.912262, 0.0250492)
(0.116079, 0.387601) (0.804606, 0.81485)
This can be rounded as:
julia> (x->round.(x;digits=2)).(mx)
3×2 Matrix{Tuple{Float64, Float64}}:
(0.62, 0.07) (0.08, 0.03)
(0.33, 0.24) (0.91, 0.03)
(0.12, 0.39) (0.8, 0.81)

How can I plot these in matlab or R

I have three expressions namely
$\frac{a^2(1-b)}{a+b-ab}+(1-a)a $
$\frac{ab}{a+b-ab}$
$(1-a)^2$
and I want to draw a plot in a-b coordinate when the first one is the biggest in yellow, when the second one is the biggest in blue, when the third one is the biggest in red.(Why latex doesnot work)
How can I deal with that problem.
Your question isn't 100% clear, but I believe this is what you're asking for. I've used Matlab.
len = 1000;
a_ = linspace(0, 5, len);
b_ = linspace(0, 5, len);
x = zeros(len);
for a = 1:len
for b = 1:len
val(1) = (a_(a)^2 * (1-b_(b))) / (a_(a) + b_(b) - a_(a)*b_(b)) + (1-a_(a))*a_(a);
val(2) = a_(a)*b_(b) / (a_(a) + b_(b) - a_(a)*b_(b));
val(3) = (1 - a_(a))^2;
if max(val) == val(1)
x(a,b) = 0.2;
elseif max(val) == val(2)
x(a,b) = 0;
elseif max(val) == val(3)
x(a,b) = 0.65;
end
end
end
imagesc(x)
colormap('hsv')
caxis([0 1])
set(gca, 'XTick', linspace(0, len, 5))
set(gca, 'YTick', linspace(0, len, 5))
set(gca, 'XTickLabel', linspace(0, 5, 5))
set(gca, 'YTickLabel', linspace(0, 5, 5))
I think this is right. I have no way of testing it unfortunately, but hopefully it does what you're after. It's possible I made a typo so let me know if it doesn't work. Obviously you can change parts to suit you.

Walking through multidimensional space in a proper way

Assuming I have a vector of say four dimensions in which every variable lays in a special interval. Thus we got:
Vector k = (x1,x2,x3,x4) with x1 = (-2,2), x2 = (0,2), x3 = (-4,1), x4 = (-1,1)
I am only interested in the points constraint by the intervals.
So to say v1 = (0,1,2,0) is important where v2 = (-5,-5,5,5) is not.
In additon to that the point i+1 should be relatively close to point i among my journey. Therefore I dont want to jump around in space.
Is there a proper way of walking through those interesting points?
For example in 2D space with x1,x2 = (-2,2) like so:
Note: The frequenz of the red line could be higher
There are many ways to create a space-filling curve while preserving closeness. See the Wikipedia article for a few examples (some have associated algorithms for generating them): https://en.wikipedia.org/wiki/Space-filling_curve
Regardless, let's work with your zig-zag pattern for 2D and work on extending it to 3D and 4D. To extend it into 3D, we just add another zig to the zig-zag. Take a look at the (rough) diagram below:
Essentially, we repeat the pattern that we had in 2D but we now have multiple layers that represent the third dimension. The extra zig that we need to add is the switch between bottom-to-top and top-to-bottom every layer. This is pretty simple to abstract:
In 2D, we have x and y axes.
We move across the x domain switching between positive and negative
directions most frequently.
We move across the y domain once.
In 3D, we have x, y, and z axes.
We move across the x domain switching between positive and negative directions most frequently.
We move across the y domain switching between positive and negative directions second most frequently.
We move across the z domain once.
It should be clear how this generalizes to higher dimensions. Now, I'll present some (Python 3) code that implements the zig-zag pattern for 4D. Let's represent the position in 4D space as (x, y, z, w) and the ranges in each dimension as (x0, x1), (y0, y1), (z0, z1), (w0, w1). These are our inputs. Then, we also define xdir, ydir, and zdir to keep track of the direction of the zig-zag.
x, y, z, w = x0, y0, z0, w0
xdir, ydir, zdir = +1, +1, +1
for iw in range(w1 - w0):
for iz in range(z1 - z0):
for iy in range(y1 - y0):
for ix in range(x1 - x0):
print(x, y, z, w)
x = x + xdir
xdir = -xdir
print(x, y, z, w)
y = y + ydir
ydir = -ydir
print(x, y, z, w)
z = z + zdir
zdir = -zdir
print(x, y, z, w)
w = w + 1
This algorithm has the guarantee that no two points printed out after each other have a distance greater than 1.
Using recursion, you can clean this up to make a very nice generalizable method. I hope this helps; let me know if you have any questions.
With the work of #Matthew Miller I implemented this generalization for any given multidimenisonal space:
'''assuming that we take three points out of our intervals [0,2] for a,b,c
which every one of them is corresponding to one dimension i.e. a 3D-space'''
a = [0,1,2]
b = [0,1,2]
c = [0,1,2]
vec_in = []
vec_in.append(a)
vec_in.append(b)
vec_in.append(c)
result = []
hold = []
dir = [False] * len(vec_in)
def create_points(vec , index, temp, desc):
if (desc):
loop_x = len(vec[index])-1
loop_y = -1
loop_z = -1
else:
loop_x = 0
loop_y = len(vec[index])
loop_z = 1
for i in range(loop_x,loop_y,loop_z):
temp.append(vec[index][i])
if (index < (len(vec) - 1)):
create_points(vec, index + 1, temp, dir[index])
else:
u = []
for k in temp:
u.append(k)
result.append(u)
temp.pop()
if (dir[index] == False):
dir[index] = True
else:
dir[index] = False
if len(temp) != 0:
temp.pop()
#render
create_points(vec_in, 0, hold, dir[0])
for x in (result):
print(x)
The result is a journey which covers every possible postion in a continous way:
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 1, 2]
[0, 1, 1]
[0, 1, 0]
[0, 2, 0]
[0, 2, 1]
[0, 2, 2]
[1, 2, 2]
[1, 2, 1]
[1, 2, 0]
[1, 1, 0]
[1, 1, 1]
[1, 1, 2]
[1, 0, 2]
[1, 0, 1]
[1, 0, 0]
[2, 0, 0]
[2, 0, 1]
[2, 0, 2]
[2, 1, 2]
[2, 1, 1]
[2, 1, 0]
[2, 2, 0]
[2, 2, 1]
[2, 2, 2]

Learning Binary Search in python 3.7

I found this code on https://www.geeksforgeeks.org/binary-search/
# Python Program for recursive binary search.
# Returns index of x in arr if present, else -1
def binarySearch (arr, l, r, x):
# Check base case
if r >= l:
mid = l + (r - l)/2;
# If element is present at the middle itself
if arr[mid] == x:
return mid
# If element is smaller than mid, then it
# can only be present in left subarray
elif arr[mid] > x:
return binarySearch(arr, l, mid-1, x)
# Else the element can only be present
# in right subarray
else:
return binarySearch(arr, mid+1, r, x)
else:
# Element is not present in the array
return -1
# Test array
arr = [ 2, 3, 4, 10, 40, 50, 80, 140, 200, 2000, 100]
x = 50
# Function call
result = binarySearch(arr, 0, len(arr)-1, int)
if result != -1:
print ("Element is present at index %d" % result)
else:
print ("Element is not present in array")
However, when I run it I get this problem: TypeError: list indices must be integers or slices, not float
I'm not sure how to convert do that. I attempted to set the entire array as an int but that didn't work or replace x with int and that didn't work either.
Any suggestion?
The issue is on this line:
mid = l + (r - l)/2;
In Python 3 / does floating point division and as mid is used as an array index it needs to be an int. To do integer division use //
mid = l + (r - l) // 2;
There is also another issue with the call to the function:
result = binarySearch(arr, 0, len(arr) - 1, int)
The last parameter should not be int but x (the variable you are searching for):
result = binarySearch(arr, 0, len(arr) - 1, x)
when you pass in int as the last parameter you'll get an error TypeError: unorderable types: int() > type()

Can Arg function in R give values greater than pi?

In R, the function Arg applied to a complex returns an angle between -pi and +pi. For example :
Arg((1+i)^5) = -2.356... (-3*pi/4 radians)
Could I have a function returning the positive angle, even greater than +pi? For example, I would like to have :
"function"((1+i)^5) = 3.926... (5*pi/4 radians)
It seems Arg is not adaptable ; maybe some other function exits in some package ?
Thanks for any help.
5*pi/4 is the same as -3*pi/4. So you could do:
Arg_positive = function(complex) {
initial = Arg(complex)
ifelse(initial < 0,
initial + 2*pi,
initial)
}
Just take the remainder of the division to 2pi:
Arg((1+1i)^5) %% (2*pi)
#[1] 3.926991
You could create your own function to address this issue.
pos.arg <- function(num)
{
arg = Arg(num)
if (arg < 0)
arg <- arg + 2*pi
arg
}
x <- complex(length.out = 1, 1, 1)
y <- x^5
pos.arg(y)
[1] 3.926991

Resources