I am trying to set (PolyA a) and (PolyB a) to be instances of class Polynomial, where I want to implement coeffs, fromCoeffs, coeffsB, fromCoeffsB. I am not quite sure what am I doing wrong, because I receive an error message saying that my functions are not visible to the class Polynomial. Any help please?
class Polynomial p where
--default implementations
data PolyA a = Coeffs [a]
deriving (Show)
data PolyB a = Const a | X (PolyB a) a
deriving (Show)
--instances
instance Polynomial (PolyA a) where
coeffs (Coeffs f)=f
fromCoeffs f= Coeffs f
instance Polynomial (PolyB a) where
coeffsB (Const f)= [f]
coeffsB (X f a)= coeffsB f ++ [a]
fromCoeffsB [] = error "Wrong Input!"
fromCoeffsB [f]= Const f
fromCoeffsB lis#(_:t)= X (fromCoeffsB (init lis)) (last lis)
The following code compiles for me:
class Polynomial p where
coeffs :: p a -> [a]
fromCoeffs :: [a] -> p a
--default implementations
data PolyA a = Coeffs [a]
deriving (Show)
data PolyB a = Const a | X (PolyB a) a
deriving (Show)
--instances
instance Polynomial PolyA where
coeffs (Coeffs f)=f
fromCoeffs f= Coeffs f
instance Polynomial PolyB where
coeffs (Const f)= [f]
coeffs (X f a)= coeffs f ++ [a]
fromCoeffs [] = error "Wrong Input!"
fromCoeffs [f]= Const f
fromCoeffs lis#(_:t)= X (fromCoeffs (init lis)) (last lis)
Summary of changes:
Add methods to the Polynomial class declaration.
Remove the type arguments in the instance declarations.
Change coeffsB to coeffs and fromCoeffsB to fromCoeffs everywhere.
Outdent the PolyB instance declaration by one space.
Related
I am trying to create a function that takes an expression and evaluates it. Expressions can contain the following operations:
Integers - described by a tuple int(N), where N is an integer.
Addition - described by a tuple add(X Y), where both X and Y are arithmetic expressions.
Multiplication - described by a tuple mul(X Y), where both X and Y are arithmetic
expressions.
Variables - described by a tuple var(A), where A is an atom giving the variable name
An environment - described by a record env(a:5 b:5), where a and b are variables with values of 5.
For example: {Eval add(var(a) mul(int(3) var(b))) env(a:5 b:5)}. Which should evaluate to 20.
So far, I have implemented integers, addition, and multiplication. But I'm not really sure where to start for the variables and the environment.
My current code:
fun {Eval X}
case X of int(N) then N
[] add(X Y) then {Eval X} + {Eval Y}
[] mul(X Y) then {Eval X} * {Eval Y}
end
end
You need to get the value of the variable from the environment. This can be done by passing the env() as parameter to the Eval function, in order to access it from inside.
I have solved it for you. It should be easy to understand.
fun {Eval Statements Env}
case Statements of int(N) then N
[] add(X Y) then {Eval X Env} + {Eval Y Env}
[] mul(X Y) then {Eval X Env} * {Eval Y Env}
[] var(X) then Env.X
end
end
As a side note, this is practically how a common interpreter runs a programming script. By using statement stack and environment to store variable mappings.
I am trying to build a deep learning model in julia. I have two models m1 and m2 which are neural networks. Here is my code:
using Flux
function even_mask(x)
s1, s2 = size(x)
weight_mask = zeros(s1, s2)
weight_mask[2:2:s1,:] = ones(Int(s1/2), s2)
return weight_mask
end
function odd_mask(x)
s1, s2 = size(x)
weight_mask = zeros(s1, s2)
weight_mask[1:2:s1,:] = ones(Int(s1/2), s2)
return weight_mask
end
function even_duplicate(x)
s1, s2 = size(x)
x_ = zeros(s1, s2)
x_[1:2:s1,:] = x[1:2:s1,:]
x_[2:2:s1,:] = x[1:2:s1,:]
return x_
end
function odd_duplicate(x)
s1, s2 = size(x)
x_ = zeros(s1, s2)
x_[1:2:s1,:] = x[2:2:s1,:]
x_[2:2:s1,:] = x[2:2:s1,:]
return x_
end
function Even(m)
x -> x .+ even_mask(x).*m(even_duplicate(x))
end
function InvEven(m)
x -> x .- even_mask(x).*m(even_duplicate(x))
end
function Odd(m)
x -> x .+ odd_mask(x).*m(odd_duplicate(x))
end
function InvOdd(m)
x -> x .- odd_mask(x).*m(odd_duplicate(x))
end
m1 = Chain(Dense(4,6,relu), Dense(6,5,relu), Dense(5,4))
m2 = Chain(Dense(4,7,relu), Dense(7,4))
forward = Chain(Even(m1), Odd(m2))
inverse = Chain(InvOdd(m2), InvEven(m1))
function loss(x)
z = forward(x)
return 0.5*sum(z.*z)
end
opt = Flux.ADAM()
x = rand(4,100)
for i=1:100
Flux.train!(loss, Flux.params(forward), x, opt)
println(loss(x))
end
The forward model is a combination of m1 and m2. I need to optimize m1 and m2 so I could optimize both forward and inverse models. But it seems that params(forward) is empty. How could I train my model?
I don't think plain functions can be used as layers in Flux. You need to use the #functor macro to add the extra functionality to collect parameters: https://fluxml.ai/Flux.jl/stable/models/basics/#Layer-helpers-1
In your case, rewriting Even, InvEven, Odd and InvOdd like this should help:
struct Even
model
end
(e::Even)(x) = x .+ even_mask(x).*e.model(even_duplicate(x))
Flux.#functor Even
After adding this definition,
Flux.params(Even(m1))
Should return a non-empty list
EDIT
An even simpler way to implement Even and friends is to use the built-in SkipConnection layer:
Even(m) = SkipConnection(Chain(even_duplicate, m),
(mx, x) -> x .+ even_mask(x) .* mx)
I suspect this is a version difference, but with Julia 1.4.1 and Flux v0.10.4, I get the error BoundsError: attempt to access () at index [1] when running your training loop, I need to replace the data with
x = [(rand(4,100), 0)]
Otherwise the loss is applied to each entry in the array x. since train! splats loss over x.
The next error mutating arrays is not supported is due to the implementation of *_mask and *_duplicate. These functions construct an array of zeros and then mutate it by replacing values from the input.
You can use Zygote.Buffer to implement this code in a way that can be differentiated.
using Flux
using Zygote: Buffer
function even_mask(x)
s1, s2 = size(x)
weight_mask = Buffer(x)
weight_mask[2:2:s1,:] = ones(Int(s1/2), s2)
weight_mask[1:2:s1,:] = zeros(Int(s1/2), s2)
return copy(weight_mask)
end
function odd_mask(x)
s1, s2 = size(x)
weight_mask = Buffer(x)
weight_mask[2:2:s1,:] = zeros(Int(s1/2), s2)
weight_mask[1:2:s1,:] = ones(Int(s1/2), s2)
return copy(weight_mask)
end
function even_duplicate(x)
s1, s2 = size(x)
x_ = Buffer(x)
x_[1:2:s1,:] = x[1:2:s1,:]
x_[2:2:s1,:] = x[1:2:s1,:]
return copy(x_)
end
function odd_duplicate(x)
s1, s2 = size(x)
x_ = Buffer(x)
x_[1:2:s1,:] = x[2:2:s1,:]
x_[2:2:s1,:] = x[2:2:s1,:]
return copy(x_)
end
Even(m) = SkipConnection(Chain(even_duplicate, m),
(mx, x) -> x .+ even_mask(x) .* mx)
InvEven(m) = SkipConnection(Chain(even_duplicate, m),
(mx, x) -> x .- even_mask(x) .* mx)
Odd(m) = SkipConnection(Chain(odd_duplicate, m),
(mx, x) -> x .+ odd_mask(x) .* mx)
InvOdd(m) = SkipConnection(Chain(odd_duplicate, m),
(mx, x) -> x .- odd_mask(x) .* mx)
m1 = Chain(Dense(4,6,relu), Dense(6,5,relu), Dense(5,4))
m2 = Chain(Dense(4,7,relu), Dense(7,4))
forward = Chain(Even(m1), Odd(m2))
inverse = Chain(InvOdd(m2), InvEven(m1))
function loss(x, y)
z = forward(x)
return 0.5*sum(z.*z)
end
opt = Flux.ADAM(1e-6)
x = [(rand(4,100), 0)]
function train!()
for i=1:100
Flux.train!(loss, Flux.params(forward), x, opt)
println(loss(x[1]...))
end
end
At this point, you get to the real fun of deep networks. After one training step, the training diverges to NaN with the default learning rate. Reducing the initial training rate to 1e-6 helps, and the loss looks like it is decreasing.
Why you can use the Hilbert epsilon operator in a method and in a function, but not in a "function method"?
method choose<T>(s:set<T>) returns (x:T)
requires s != {}
{
var z :| z in s;
return z;
}
function choose'<T>(s:set<T>):T
// function method choose'<T>(s:set<T>):T // Activate this line and comment the previous line to see the error
requires s != {}
{
var z :| z in s;
z
}
In order for the Hilbert epsilon operator, also known in Dafny as the let-such-that expression,
var z :| P; E
to be compilable, the constraint P must determine z uniquely. In your case, the constraint P is z in s, which does not determine z uniquely except for singleton sets.
If s were of type set<int>, you can (inefficiently) live up to this requirement by changing your choose' function to:
function method choose'<T>(s:set<int>):int
requires s != {}
{
var z :| z in s && forall y :: y in s ==> z <= y;
z
}
Almost. You need to convince Dafny there is such a z. You can do that in a lemma. Here's a probably-longer-than-necessary-but-the-first-thing-I-got-working lemma that does that. Note that the lemma also uses the Hilbert operator, but in a statement context, so the uniqueness requirement does not apply.
function method choose'<T>(s:set<int>):int
requires s != {}
{
HasMinimum(s);
var z :| z in s && forall y :: y in s ==> z <= y;
z
}
lemma HasMinimum(s: set<int>)
requires s != {}
ensures exists z :: z in s && forall y :: y in s ==> z <= y
{
var z :| z in s;
if s == {z} {
// the mimimum of a singleton set is its only element
} else if forall y :: y in s ==> z <= y {
// we happened to pick the minimum of s
} else {
// s-{z} is a smaller, nonempty set and it has a minimum
var s' := s - {z};
HasMinimum(s');
var z' :| z' in s' && forall y :: y in s' ==> z' <= y;
// the minimum of s' is the same as the miminum of s
forall y | y in s
ensures z' <= y
{
if
case y in s' =>
assert z' <= y; // because z' in minimum in s'
case y == z =>
var k :| k in s && k < z; // because z is not minimum in s
assert k in s'; // because k != z
}
}
}
Unfortunately, the type of your s is not set<int>. I don't know how to get a unique value from a general set. :(
For information about why the uniqueness requirement is important in compiled expressions see this paper.
Rustan
I'm trying to calculate Euler-Lagrange equations for a robotic structure.
I'll use q to indicate the vector of the joint variables.
In my code, I use
syms t;
q1 = sym('q1(t)');
q2 = sym('q2(t)');
q = [q1, q2];
to declare that q1 and q2 depend on time t.
After I calculate the Lagrangian L (in this case it is a simple link with a rotoidal joint)
L = (I1z*diff(q1(t), t)^2)/2 + (L1^2*M1*diff(q1(t), t)^2)/8
The problem is that when I try to differentiate L respect to q using diff(L, q), I get this error
Error using sym/diff (line 69)
The second argument must be a variable or a nonnegative integer specifying the number of differentiations.
How can I differentiate L respect to q to have the first term of the Euler-Lagrange equation?
I also tried to write q simply as
syms q1 q2
q = [q1 q2]
without the time dependency but differentiation will not work, i.e. will obviously give me [0, 0]
That's what I've got in the workspace (I1z is the inertia of the link respect to z-axis, M1 is the mass of the link, L1 is the length of the link)
q = [q1(t), q2(t)]
diff(q, t) = [diff(q1(t), t), diff(q2(t), t)]
L = (I1z*diff(q1(t), t)^2)/2 + (L1^2*M1*diff(q1(t), t)^2)/8
If you want to run the full code, you have to download all the .m files from here and then use
[t, q, L, M, I] = initiate();
L = lagrangian(odof(q, L), q, M, I, t, 1)
otherwise the following code should be the same.
syms t I1z L1 M1
q1 = sym('q1(t)');
q2 = sym('q2(t)');
q = [q1, q2];
qp = diff(q, t);
L = (I1z*qp(1)^2)/2 + (L1^2*M1*qp(1)^2)/8;
EDIT
Thanks to AVK's answer I realized the problem.
Example 1 (AVK's code)
syms t q1 q2 q1t q2t I1z L1 M1 % variables
L = (I1z*q1t^2)/2 + (L1^2*M1*q1t^2)/8
dLdqt = [diff(L,q1t), diff(L,q2t)]
This will work and its result will be
dLdqt = [(M1*q1t*L1^2)/4 + I1z*q1t, 0]
Example 2 (wrong)
syms t q1 q2 q1t q2t I1z L1 M1
L = (I1z*q1t^2)/2 + (L1^2*M1*q1t^2)/8;
qt = [q1t q2t];
dLdqt = diff(L, qt)
This will not work, because diff expects a single variable of differentiation
Example 3 (right)
syms t q1 q2 q1t q2t I1z L1 M1
L = (I1z*q1t^2)/2 + (L1^2*M1*q1t^2)/8;
qt = [q1t q2t];
dLdqt = jacobian(L, qt)
This will work, because jacobian expects at least a variable of differentiation
EDIT 2
Seems that MATLAB's Symbolit Toolbox can't handle differentiation with respect to q(t), so you have to use the variable q.
So using these as functions
q = [q1(t), q2(t), q3(t), q4(t), q5(t), q6(t)]
qp = [diff(q1(t), t), diff(q2(t), t), diff(q3(t), t), diff(q4(t), t), diff(q5(t), t), diff(q6(t), t)]
and these as variables
qv = [q1, q2, q3, q4, q5, q6];
qvp = [q1p, q2p, q3p, q4p, q5p, q6p];
solved the problem.
The whole code will looks like this
syms q1 q2 q3 q4 q5 q6;
syms q1p q2p q3p q4p q5p q6p;
qv = [q1, q2, q3, q4, q5, q6];
qvp = [q1p, q2p, q3p, q4p, q5p, q6p];
Lagv = subs(Lag, [q, qp], [qv, qvp]);
dLdq = jacobian(Lagv, qv);
dLdqp = jacobian(Lagv, qvp);
dLdq = subs(dLdq, [qv, qvp], [q, qp]);
dLdqp = subs(dLdqp, [qv, qvp], [q, qp]);
m_eq = diff(dLdqp, t) - dLdq;
If you want to differentiate L with respect to q, q must be a variable. You can use subs to replace it with a function and calculate
later:
syms t q1 q2 q1t q2t I1z L1 M1 % variables
L = (I1z*q1t^2)/2 + (L1^2*M1*q1t^2)/8
dLdqt= [diff(L,q1t), diff(L,q2t)]
dLdq = [diff(L,q1), diff(L,q2)]
syms q1_f(t) q2_f(t) % functions
q1t_f(t)= diff(q1_f,t)
q2t_f(t)= diff(q2_f,t)
% replace the variables with the functions
dLdq_f= subs(dLdq,{q1 q2 q1t q2t},{q1_f q2_f q1t_f q2t_f})
dLdqt_f= subs(dLdqt,{q1 q2 q1t q2t},{q1_f q2_f q1t_f q2t_f})
% now we can solve the equation
dsolve(diff(dLdqt_f,t)-dLdq_f==0)
I developed the Euler-Lagrange Library in MATLAB, with a list of illustrative examples. you can download it using the following link:
https://www.mathworks.com/matlabcentral/fileexchange/86563-matlab-euler-lagrange-library
class X
class Y extends X
class Z extends Y
class M {
def f(x: X): String = "f with X at M"
def f(x: Y): String = "f with Y at M"
}
class N extends M {
override def f(x: Y): String = "f with Y at N"
def f(x: Z): String = "f with Z at N"
}
val z: Z = new Z
val y: Y = z
val x: X = y
val m: M = new N
println(m.f(x))
// m dynamically matches as type N and sees x as type X thus goes into class M where it calls "f with X at M"
println(m.f(y))
// m dynamically matches as type N and sees y as type Y where it calls "f with Y at N"
println(m.f(z))
// m dynamically matches as type N and sees z as type Z where it calls "f with Z at N"
Consider this code, I don't understand with the final call println(m.f(z)) doesn't behave as I wrote in the comments - is there a good resource for understanding how overloading works in Scala?
Thank!
Firstly overloading in Scala works the same as in Java.
Secondly, it's about static and dynamic binding. Let's find out what compiler see. You have m: M object. Class M has f(X) and f(Y) methods. When you call m.f(z) compiler resolves that method f(Y) should be called because Z is subclass of Y. It's a very important point: compiler doesn't know real class of m object that's why it knows nothing about method N.f(Z). And it's called static binding: compiler resolves method's signature. Later, in runtime, dynamic binding happens. JVM knows real class of m and it calls f(Y) which is overloaded in Z.
Hope my explanations are clearly enough to understand.
class x
class Y extends X
class Z extends Y
class M {
def f(x: X): String = "f with X at M"
def f(x: Y): String = "f with Y at M"
}
class N extends M {
override def f(x: Y): String = "f with Y at N"
def f(x: Z): String = "f with Z at N"
}
val z: Z = new Z
val y: Y = z
val x: X = y
val m: M = new N
println(m.f(x))
// m dynamically matches as type N and sees x as type X thus goes into class M where it calls "f with X at M"
println(m.f(y))
// m dynamically matches as type N and sees y as type Y where it calls "f with Y at N"
println(m.f(z))
// m dynamically matches as type N and sees z as type Z where it calls "f with Z at N"
Because the function will be overloaded on N.so N is depends on m.f(y) .finally it is related with x and y that is reason z function will call
When you do this
val m: M = new N
It means that m is capable of doing everything that class M can. M has two methods - first which can take X, other Y.
And hence when you do this
m.f(z)
Runtime is going to search for a method which can accept z (of type Z). The method in N is not a candidate here because of two reasons
The reference is of type M
Your N does not override any method of M which can accept an argument of type Z. You do have a method in N which can accept a Z but that's not a candidate because it's not overriding anything from M
The best match is f in M which can accept a Y this is because Z ISA Y
You can get what your last comment says if
You define a method in M which takes argument of type Z and then you override it in N
You instantiate a val of type N e.g: val m : N = new N
I think the existing questions on SO already elaborate this point.