Subtracting variables in Rails - ruby-on-rails

Im trying to see if a point is within a circle.I am using the Pythagorean Theorem to check, but when I use this I get undefined method-' for "37.33259551999998":String`. How do I subtract these variables?
def getalerts
alerts = Alert.all
school = School.find_by_school_name(params[:school])
latitude = params[:latitude]
longitude = params[:longitude]
radius = school.radius
alertArray = Array.new()
alerts.each do |alert|
d = Math.sqrt(((alert.latitude - school.latitude)**2) + (alert.longitude - school.longitude)**2)
if d < radius
alertArray["latlng"] = alert.latitude, alert.longitude
end
end
respond_to do |format|
format.json { render json: alertArray}
end
end

Use to_f on alert and school latitudes and longitudes.
Converting to float will preserve decimal point numbers (unlike to_i)
d = Math.sqrt(
((alert.latitude.to_f - school.latitude.to_f)**2)
+ (alert.longitude.to_f - school.longitude.to_f)**2)

From the error message, it is clear that subtraction option is performed on strings and hence it is not valid. You can convert strings to integers using to_i method. So try this :
d = Math.sqrt(((alert.latitude.to_i - school.latitude.to_i)**2) + (alert.longitude.to_i - school.longitude.to_i)**2)
Also, if you want them converted to floating values, you will have to use to_f method.

Cary makes the correct point. Even if the initial question is about a technical problem with tying to subtract string representations of floating point numbers, the real issue is that you need to calculate the distance between two points on the earth. Here is a ruby implementation of the haversine formula
https://github.com/kristianmandrup/haversine/blob/master/lib/haversine.rb

Related

move object along measured curve in manim

I'm trying to find a sensible way to move an Mobject along a path defined by the n-length vectors ts,xs,ys,(zs).
The solution I have now is by using ParametricFunction and MoveAlongPath. I can then define a rate function to make sure the timing adds up. This is extremely backwards and not quite reliable in my experience.
I feel like I'm probably missing some builtin function but I can't find it.
# This function takes a path defined by arrays and returns a function
# ts is assumed to be strictly increasing
def manim_curve(ts,xs,ys):
ts,xs,ys = map(np.array,(ts,xs,ys))
# Calculate the total distance traveled over the curve
dist = np.cumsum(np.abs(np.diff(xs+1j*ys,prepend=0)))
# Normalize to a time range of [0,1]
nts = ts / ts[-1]
ndist = dist / dist[-1]
# Create a function that can be passed `ParametricFunction`
def f(t):
n = np.abs(nts-t).argmin() # Find index from t
return (xs[n],ys[n],0)
# Create a rate function for `MoveAlongPath`
def rate(t):
n = np.abs(nts-t).argmin() # Find index from t
return ndist[n]
# Create manim curve
curve = ParametricFunction(function=f)
return curve,rate
# Animation class to move along a discretely defined path
class MoveAlongMeasuredPath(MoveAlongPath):
def __init__(self,object,ts,xs,ys,**kwargs):
ts,xs,ys = map(np.array,(ts,xs,ys))
curve,rate = manim_curve(ts,xs,ys)
super().__init__(object,curve,
run_time = ts[-1],
rate_func = rate,
**kwargs)
The best way to move an Mobject along a path defined by the n-length vectors ts,xs,ys,(zs) is to use the ParametricFunction and MoveAlongPath functions. This will allow you to define a path using the vectors and then move the Mobject along that path. It is a reliable and straightforward way to achieve this.
I dug a little deeper in the code and realized there is a simple solution. The class below is only a slight alteration of the MoveAlongPath class source code:
class MoveAlongTXYZPath(Animation):
def __init__(
self,
mobject: Mobject,
ts:NDArray,
points:NDArray,
is_sorted:bool=False,
suspend_mobject_updating: bool = False,
**kwargs,
) -> None:
assert np.all(ts>=0), "no negative t_values allowed"
assert len(ts)==len(points), "vectors have to be the same length"
# Sort if unsorted in t
if not is_sorted:
ts,points = map(np.array,zip(*sorted([*zip(ts,points)])))
self.points = points
run_time = np.max(ts)
self.alphas = ts/run_time
super().__init__( mobject,
suspend_mobject_updating=suspend_mobject_updating,
run_time=run_time,
rate_func=linear,
**kwargs)
def interpolate_mobject(self, alpha: float) -> None:
index = np.searchsorted(self.alphas,alpha)
point = self.points[index]
self.mobject.move_to(point)

Index values from table into another table

I want to store the values by selecting the keys of a table into another table, for example:
polyline = {color="blue", thickness=2, npoints=4}
stuff = {"polyline.color":[polyline.thickness]}
print(stuff)
Should produce:
blue 2
However, I get the following error:
input:3: '}' expected near ':'
local polyline = {color="blue", thickness=2, npoints=4}
local stuff = {polyline.color, polyline.thickness}
print(table.unpack(stuff))
I believe, You're mixing in some Python syntax. Do you notice using two different (wrong) ways of accessing the values?
I guess, this is what You've meant with your snippet of Lua code:
polyline = {color = "blue", thickness = 2, npoints = 4}
stuff = {[polyline.color] = polyline.thickness}
for key, val in pairs(stuff) do
print(key, val)
end

no method matching logpdf when sampling from uniform distribution

I am trying to use reinforcement learning in julia to teach a car that is constantly being accelerated backwards (but with a positive initial velocity) to apply brakes so that it gets as close to a target distance as possible before moving backwards.
To do this, I am making use of POMDPs.jl and crux.jl which has many solvers (I'm using DQN). I will list what I believe to be the relevant parts of the script first, and then more of it towards the end.
To define the MDP, I set the initial position, velocity, and force from the brakes as a uniform distribution over some values.
#with_kw struct SliderMDP <: MDP{Array{Float32}, Array{Float32}}
x0 = Distributions.Uniform(0., 80.)# Distribution to sample initial position
v0 = Distributions.Uniform(0., 25.) # Distribution to sample initial velocity
d0 = Distributions.Uniform(0., 2.) # Distribution to sample brake force
...
end
My state holds the values of (position, velocity, brake force), and the initial state is given as:
function POMDPs.initialstate(mdp::SliderMDP)
ImplicitDistribution((rng) -> Float32.([rand(rng, mdp.x0), rand(rng, mdp.v0), rand(rng, mdp.d0)]))
end
Then, I set up my DQN solver using crux.jl and called a function to solve for the policy
solver_dqn = DQN(π=Q_network(), S=s, N=30000)
policy_dqn = solve(solver_dqn, mdp)
calling solve() gives me the error MethodError: no method matching logpdf(::Distributions.Categorical{Float64, Vector{Float64}}, ::Nothing). I am quite sure that this comes from the initial state sampling, but I am not sure why or how to fix it. I have only been learning RL from various books and online lectures for a very short time, so any help regarding the error or my the model I set up (or anything else I'm oblivious to) would be appreciated.
More comprehensive code:
Packages:
using POMDPs
using POMDPModelTools
using POMDPPolicies
using POMDPSimulators
using Parameters
using Random
using Crux
using Flux
using Distributions
Rest of it:
#with_kw struct SliderMDP <: MDP{Array{Float32}, Array{Float32}}
x0 = Distributions.Uniform(0., 80.)# Distribution to sample initial position
v0 = Distributions.Uniform(0., 25.) # Distribution to sample initial velocity
d0 = Distributions.Uniform(0., 2.) # Distribution to sample brake force
m::Float64 = 1.
tension::Float64 = 3.
dmax::Float64 = 2.
target::Float64 = 80.
dt::Float64 = .05
γ::Float32 = 1.
actions::Vector{Float64} = [-.1, 0., .1]
end
function POMDPs.gen(env::SliderMDP, s, a, rng::AbstractRNG = Random.GLOBAL_RNG)
x, ẋ, d = s
if x >= env.target
a = .1
end
if d+a >= env.dmax || d+a <= 0
a = 0.
end
force = (d + env.tension) * -1
ẍ = force/env.m
# Simulation
x_ = x + env.dt * ẋ
ẋ_ = ẋ + env.dt * ẍ
d_ = d + a
sp = vcat(x_, ẋ_, d_)
reward = abs(env.target - x) * -1
return (sp=sp, r=reward)
end
function POMDPs.initialstate(mdp::SliderMDP)
ImplicitDistribution((rng) -> Float32.([rand(rng, mdp.x0), rand(rng, mdp.v0), rand(rng, mdp.d0)]))
end
POMDPs.isterminal(mdp::SliderMDP, s) = s[2] <= 0
POMDPs.discount(mdp::SliderMDP) = mdp.γ
mdp = SliderMDP();
s = state_space(mdp); # Using Crux.jl
function Q_network()
layer1 = Dense(3, 64, relu)
layer2 = Dense(64, 64, relu)
layer3 = Dense(64, length(3))
return DiscreteNetwork(Chain(layer1, layer2, layer3), [-.1, 0, .1])
end
solver_dqn = DQN(π=Q_network(), S=s, N=30000) # Using Crux.jl
policy_dqn = solve(solver_dqn, mdp) # Error comes here
Stacktrace:
policy_dqn
MethodError: no method matching logpdf(::Distributions.Categorical{Float64, Vector{Float64}}, ::Nothing)
Closest candidates are:
logpdf(::Distributions.DiscreteNonParametric, !Matched::Real) at C:\Users\name\.julia\packages\Distributions\Xrm9e\src\univariate\discrete\discretenonparametric.jl:106
logpdf(::Distributions.UnivariateDistribution{S} where S<:Distributions.ValueSupport, !Matched::AbstractArray) at deprecated.jl:70
logpdf(!Matched::POMDPPolicies.PlaybackPolicy, ::Any) at C:\Users\name\.julia\packages\POMDPPolicies\wMOK3\src\playback.jl:34
...
logpdf(::Crux.ObjectCategorical, ::Float32)#utils.jl:16
logpdf(::Crux.DistributionPolicy, ::Vector{Float64}, ::Float32)#policies.jl:305
var"#exploration#133"(::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, ::typeof(Crux.exploration), ::Crux.DistributionPolicy, ::Vector{Float64})#policies.jl:302
exploration#policies.jl:297[inlined]
action(::Crux.DistributionPolicy, ::Vector{Float64})#policies.jl:294
var"#exploration#136"(::Crux.DiscreteNetwork, ::Int64, ::typeof(Crux.exploration), ::Crux.MixedPolicy, ::Vector{Float64})#policies.jl:326
var"#step!#173"(::Bool, ::Int64, ::typeof(Crux.step!), ::Dict{Symbol, Array}, ::Int64, ::Crux.Sampler{Main.workspace#2.SliderMDP, Vector{Float32}, Crux.DiscreteNetwork, Crux.ContinuousSpace{Tuple{Int64}}, Crux.DiscreteSpace})#sampler.jl:55
var"#steps!#174"(::Int64, ::Bool, ::Int64, ::Bool, ::Bool, ::Bool, ::typeof(Crux.steps!), ::Crux.Sampler{Main.workspace#2.SliderMDP, Vector{Float32}, Crux.DiscreteNetwork, Crux.ContinuousSpace{Tuple{Int64}}, Crux.DiscreteSpace})#sampler.jl:108
var"#fillto!#177"(::Int64, ::Bool, ::typeof(Crux.fillto!), ::Crux.ExperienceBuffer{Array}, ::Crux.Sampler{Main.workspace#2.SliderMDP, Vector{Float32}, Crux.DiscreteNetwork, Crux.ContinuousSpace{Tuple{Int64}}, Crux.DiscreteSpace}, ::Int64)#sampler.jl:156
solve(::Crux.OffPolicySolver, ::Main.workspace#2.SliderMDP)#off_policy.jl:86
top-level scope#Local: 1[inlined]
Short answer:
Change your output vector to Float32 i.e. Float32[-.1, 0, .1].
Long answer:
Crux creates a Distribution over your network's output values, and at some point (policies.jl:298) samples a random value from it. It then converts this value to a Float32. Later (utils.jl:15) it does a findfirst to find the index of this value in the original output array (stored as objs within the distribution), but because the original array is still Float64, this fails and returns a nothing. Hence the error.
I believe this (converting the sampled value but not the objs array and/or not using approximate equality check i.e. findfirst(isapprox(x), d.objs)) to be a bug in the package, and would encourage you to raise this as an issue on Github.

Some simple math isn't working in my helper

I've got a grade function:
def grade(submission)
score_counter = 0
total_score = submission.test.questions.size
#the scoring logic is here
return (score_counter/total_score)*100
end
The intention is to return a percent score, but all that shows up in my view is 0. If I just try to return score_counter and total_score separately, they display the correct values. Any ideas?
You need to change your values to float
(score_counter.to_f / total_score.to_f) * 100

Convert & store String into currency values

I have a String and i need to convert it into Currency format in RUBY and
verify whether it matches to the expected.
String = "$6,178.50 USD / 22,693.01 AED"
I want to split it into 2 different variables like
usa_price = $6,178.50
aed_price = 22,693.01
expected_output= $6,178.50 * 3.67 = 22,693.01 (should match value in AED)
I tried doing gsub/scan and im confused now, what's the best way to
achieve this in Ruby!!!
I would split on the / and then use the money gem to parse the amounts out, like this:
require 'money'
amounts = "$6,178.50 USD / 22,693.01 AED".split("/")
amounts.map! { |amount| Money.parse(amount) }
Then, because they're now Money objects, you can do money things with them:
>> amounts.first.format
=> "$6,178.50"
If you're sure that first number is USD and second number is AED and the order won't change then:
str = "$6,178.50 USD / 22,693.01 AED"
usa_price, aed_price = str.scan(/\d{1,2}?,?\d{1,3}\.\d{2}/)
#=> usa_price = 6,178.50, aed_price = 22,693.01

Resources