I know that apply f in H can be used to apply a hypothesis to a function, and I know that apply f with a b c can be used to supply the arguments it cannot infer on its own while applying f directly.
Would it be possible to use the two combined somehow?
I would recommend looking at the reference manual: https://coq.inria.fr/distrib/current/refman/proof-engine/tactics.html#coq:tacn.apply-in.
You can use apply f with ... in h with a binding list
apply f with (x := u) (0 := v) in h
but it seems that the version with just terms is reserved to apply.
This is a bit heavier but should be able to get the same results.
Related
I'm new to Maple and I'm looking for a simple way to automate some tasks. In particular, I'm looking for a way to define custom "action" that perform some steps automatically.
As as an example I would like to define a quick way to compute the determinant of the Hessian of a polynomial. Currently the way I do this is opening Maple, create a new worksheet than performing the following commands:
p := (x, y) -> x^2*y + 3*x^3 + y^3
with(VectorCalculus):
h := Hessian(p(x, y), [x, y])
Determinant(h)
What I would like to do is to compute the hessian determinant directly with something like
HessDet(p)
where HessDet would be a custom command that performs the operations above. How does one achieve something like this in Maple?
First things first: The value assigned to your p is a procedure which can return a polynomial expression, but not itself a polynomial. It's important not to muddle expressions and procedures. Doing so is a common cause of problems for new users.
Being able to throw around p(x,y) may be visually pleasing to your eye, but it serves little programmatic purpose here. The fact that the formal parameters of procedure p happen to be called x and y, along with the fact that you called procedure p with arguments x and y, is actually just another common source of confusion. Don't create procedures merely to call them in this way.
Also, your call p(x,y) makes it look magic that your code snippet "knows" how many arguments would be required by procedure p. So it's already a muddle to have your candidate HessDet accept p as a procedure.
So instead let's keep it straightforward, by writing HessDet to accept a polynomial rather than a procedure. We can programmatically ascertain the names in which this expression of of type polynom.
restart;
HessDet:=proc(p::algebraic)
local H,vars;
vars:=indets(p,
And(name,Non(constant),
satisfies(u->type(p,polynom(anything,u)))));
H:=VectorCalculus:-Hessian(p,[vars[]]);
LinearAlgebra:-Determinant(H);
end proc:
Now some examples of using it,
P := x^2*y + 3*x^3 + y^3;
HessDet(P);
p := (x, y) -> x^2*y + 3*x^3 + y^3;
HessDet(p(x,y));
HessDet(x^3-x^2+4*x);
HessDet(s^2*t + 3*s^3 + t^3);
HessDet(s[r]^2*t[r] + 3*s[r]^3 + t[r]^3);
You might also wonder how you could re-use this custom procedure across sessions, without having to type it in each time. Two reasonable ways are:
Put the (above) defining plaintext definition of HessDet inside a personal initialization file.
Create a (.mla) Maple Library Archive file, then Save your HessDet to that, and then augment the Library search path in your initialization file.
It might look like 2) is more effort, but only the Save step is needed for repeats, and you can store many custom procedures to the same archive. Your choice...
[edit] The OP has asked for clarification of the first part of the above procedure HessDet, which I suspect means the call to indets.
If P is assigned an expression then then the call indets(P,name) will return a set of all the names present in that expression. Basically, it returns the set of all indeterminate subexpressions of the expression which are of type name in Maple's technical sense.
For example,
P := x*y + sin(a*Pi)*x;
x y + sin(a Pi) x
indets( P,
name );
{Pi, a, x, y}
Perhaps the name of the constant Pi is not wanted here. Ie,
indets( P,
And( name,
Non(constant) ) );
{a, x, y}
Perhaps we want only the non-constant names in which the expression is a polynomial? Ie,
indets( P,
And( name,
Non(constant),
satisfies(u->type(p,polynom(anything,u))) ) );
{x, y}
That last result is an advanced way of using the following tests:
type(P, polynom(anything, x));
true
type(P, polynom(anything, y));
true
type(P, polynom(anything, a));
false
A central issue here is that the OP made no mention of what kind of polynomials are to be handled by the custom procedure. So I guessed with some defensive coding, in hope of less surprises later on. The original Question states that the input could be a "polynomial", but we weren't told what kind of coefficients there might be.
Perhaps the coefficients will always be real and exact or numeric. Perhaps the custon procedure should throw an error when not supplied such. These details weren't mentioned in the Question.
The tactic instantiate can take and ident or a num as:
instantiate (ident:= term)
instantiate (num := term)
Now I want to use the second one inside a tactic definition. For example:
Ltac my_instantiate n x:=
instantiate(n:=x).
Unfortunately, this gives the following error:
Ltac variable n is bound to 1 which cannot be coerced to a fresh
identifier.
I suspect that ltac is trying to use the first use of instantiate. How do I tell coq to instantiate by position, or how do I pass the argumetn correctly?
Here is a minimal example:
Ltac my_instantiate n x:=
instantiate(n:=x).
Goal exists x, x = 2.
eexists.
my_instantiate 1 2.
(* Fails with: Ltac variable n is bound to 1 which
cannot be coerced to a fresh identifier. *)
Note: I know that instantiating by position is discouraged, but I'm only using my tactic for exploration purposes.
Maybe what you are looking for can be expressed in terms of a Tactic Notation?
reference manual - tactic notations
They seem to serve similar purposes. The one difference I've noticed so far is that while Program Fixpoint will accept a compound measure like {measure (length l1 + length l2) }, Function seems to reject this and will only allow {measure length l1}.
Is Program Fixpoint strictly more powerful than Function, or are they better suited for different use cases?
This may not be a complete list, but it is what I have found so far:
As you already mentioned, Program Fixpoint allows the measure to look at more than one argument.
Function creates a foo_equation lemma that can be used to rewrite calls to foo with its RHS. Very useful to avoid problems like Coq simpl for Program Fixpoint.
In some (simple?) cases, Function can define a foo_ind lemma to perform induction along the structure of recursive calls of foo. Again, very useful to prove things about foo without effectively repeating the termination argument in the proof.
Program Fixpoint can be tricked into supporting nested recursion, see https://stackoverflow.com/a/46859452/946226. This is also why Program Fixpoint can define the Ackermann function when Function cannot.
I'm using MATLAB 2012b.
I want to get d²/dxdy of a simple function:
f(x,y) = (x-1)² + 2y²
The documentation states that I can use syms and diff as in the following example:
> syms x y
> diff(x*sin(x*y), x, y)
ans =
2*x*cos(x*y) - x^2*y*sin(x*y)
But doing the same I got the wrong answer:
> syms x y
> f = (x-1)^2 + 2*y^2;
> diff(f,x,y)
ans =
4*y
The answer is right if I use diff like this:
diff(diff(f,x),y)
Well, it's not a problem for me to use it this way, but nevertheless why is the first variant not working? Is it a version issue?
The actual documentation from R2010a:
diff(expr) differentiates a symbolic expression expr with respect to its free variable as determined by symvar.
diff(expr, v) and diff(expr, sym('v')) differentiate expr with respect to v.
diff(expr, n) differentiates expr n times. n is a positive integer.
diff(expr, v, n) and diff(expr, n, v) differentiate expr with respect to v n times.
So, the command diff(f,x,y) is the last case. It would be equal to differentiating f w.r.t. x, y times, or w.r.t y, x times.
For some reason I don't quite understand, you don't get a warning or error, but one of the syms variables gets interpreted as n = 1, and then the differentiation is carried out. In this case, what diff seems to do is basically diff(f, y, 1).
In any case, it seems that the behavior changed from version to version, because in the documentation you link to (R2016b), there is an additional case:
diff(F,var1,...,varN) differentiates F with respect to the variables var1,...,varN
So I suspect you're running into a version issue.
If you want to differentiate twice, both w.r.t x and y, your second attempt is indeed the correct and most portable way to do that:
diff( diff(f,x), y )
or equivalently
diff( diff(f,y), x )
NB
I checked the R2010a code for symbolic/symbolic/#sym/diff.m and indeed, n is defaulted to 1 and only changed if one of the input variables is a double, and the variable to differentiate over is set equal to the last syms variable in the argument list. The multiple syms variable call is not supported, nor detected and error-trapped.
Syms is only creating symbolic variables.
The first code you execute is only a single derivative. The second code you provided differentiates two times. So I think you forgot to differentiate a second time in the first piece of code you provided.
I am also wondering what answer you expect? If you want 4*y as answer, than you should use
diff(f,y)
and not
diff(f,x,y)
Performing the second derivative is giving me zero?
diff(diff(f,x),y)
If you want 4 as answer than you have to do following:
diff(diff(f,y),y)
The equations I am working with in this problem contain exponentials. For this reason, after differentiating they appear again pretty much unchanged apart from additional constants and other factors. I was wondering if it might be possible to collect those exponentials back into the name of the expression they where part of. Here is an example:
Given this function definition
f:= x -> A*exp(B/x)
After differentiating, one would get
A*exp(B/x)*(-B/x^2)
And it would be great if I could somehow convert it to
f(x)*(-B/x^2)
Is this possible with MuPad or any other CAS package?
It's easy in MAPLE, use general substitution command algsubs
> f:= x -> A*exp(B/x)
> g := diff(f(x), x)
> algsubs(A*exp(B/x) = F, g)
For more complex expressions, try collect