## dharr

Dr. David Harrington

## 5535 Reputation

19 years, 182 days
University of Victoria
Professor or university staff

## Social Networks and Content at Maplesoft.com

I am a professor of chemistry at the University of Victoria, BC, Canada, where my research areas are electrochemistry and surface science. I have been a user of Maple since about 1990.

## function conversion...

@nicolesharp100 Maple's StringTools package can do quite sophisticated substitutions based on pattern matching but here Subs (substitute all) and Substitute (substitute the first) will do the trick.

 > restart;
 > with(StringTools):
 > str:="f(x,y):=sin(x)*cos(y);";

 > str2:=Substitute(Subs([":=" = "->"],str), "(", ":=(" );

 > parse(str2);

 >

## operator syntax...

@nicolesharp100 f(x,y):=x*y is an alternative way to enter an operator definition. The f:=(x,y)->x*y; (which I prefer) emphasizes that you are storing a procedure in the variable f; f:=proc(x,y) x*y end proc; does the same thing. If you use the arrow notation (also used in math), then f(0,0):=1 is used to set (in a remember table) a specific value for arguments (0,0).

## similar question...

You seem to have asked a similar question here.

## yes...

@acer Yes, I saw that; I said "as documented" in my question. My point is I'm not sure why it is designed that way. Functionally, if I make a Matrix with fill=6 and assign some values with an initializer or by later assigning values, I use that Matrix knowing all the others values I retrieve will be 6. Now I decide I only have a few values to assign, so I think I'll change to storage = sparse. So now I would think it can functionally work the same; the fill value is just stored once and returned when I request an unstored value. It seems strange I now have to write a custom indexing function for a situation that is not that different. In fact the default fill value of zero works in just this way for sparse storage; it just can't be changed to some other value.

For backward compatibility, I'm sure modifying the way fill works is a bad idea, but I think some way to change the default fill value to other than zero would be useful.

## you understood correctly...

@mmcdara Yes, you understood correctly.

## solve...

@ijuptilk Christian's answer is a better one for the roots command. For just finding the maximum amount of information, use solve. For the (very long) general formula for a cubic, use

solve(a*x^3+b*x^2+c*x+d,x,explicit);

If the  coefficients have (exact) values, use solve also. (But if you only want numerical roots, use fsolve.)

## full evaluation...

@mmcdara V[2] evaluates to 1. Try addressof(V[2]) and addressof(1) and you see they are the same.

(op(V) shows that there are 3 separate entries in the Vector.)

## indexing function works...

@acer Thanks. (not sure why the fill value couldn't serve this purpose.)

## accessing default value other than zero....

@mmcdara I agree that the storage is sparse. What I want is that (as for the table example) when I ask for one of the unstored values in the sparse case, say V[5], I get a default value back. It seems that the default value has to be zero, it can't be set to anything else (like {}, for example).

## exp...

Your f := u -> e^(-theta*u) (and elsewhere) uses "e", which has no special meaning in Maple. Use f := u -> exp(-theta*u) instead. Or in the common symbols palette choose the e next to Pi. Notice in the output that the ordinary e is in italics, but the exp e is not.

@Carl Love Thanks. Just to clarify, although I developed both algorithms, the idea of the labeled adjacency matrix giving the walks is not new, for example it is found here.

## another version...

@Carl Love Thanks for the comments. The makesets code with the expand is only used for one entry of the matrix (for the vertex of interest), so if you wanted to calculate for all vertices it certainly wouldn't be good. Here's another version that has less explosive storage requirements because it condenses the entries to sums of vertex sets at each stage. The basic idea was to use LinearAlgebra:-Generic for Matrix multiplication with `*` defined as set union, but there was code creep to deal with multiples of sets (2*{1,4,5}), so it has less storage but is probably too inefficient. Could perhaps use something like f(1,2,3)*f(2,3,4)=f(1,2,3,4) instead.

WalkLength:=proc(G::Graph,v)
uses GraphTheory;
local x,y,u,vv,A,B,F,n,vertset,i,omega;
if not member(v,Vertices(G),'vv') then error "vertex not in graph" end if;
if not IsConnected(G) then return infinity end if;
F[`0`]:=0:F[`1`]:=1:F[`=`]:=(x,y)->evalb(x=y):F[`/`]:=`/`:
F[`+`]:=()->map(u->if type(u,`*`) then op(2,u) else u end if,`+`(args));
F[`*`]:=proc(x,y) local i,j,q,u;
if x=0 or y=0 then return 0
elif x::set and y::set then
return x union y
elif x::set and type(y,`+`) then
q:=map(`union`,y,x);
return map(u->if type(u,`*`) then op(2,u) else u end if,q)
elif y::set and type(x,`+`) then
q:=map(`union`,x,y);
return map(u->if type(u,`*`) then op(2,u) else u end if,q)
elif type(x,`+`) and type(y,`+`) then
return map(u->if type(u,`*`) then op(2,u) else u end if,q)
else error "unexpected error"
end if
end proc;
n:=NumberOfVertices(G);
vertset:={\$(1..n)};
B:=copy(A);
for i from 2 do
B:=LinearAlgebra:-Generic:-MatrixMatrixMultiply[F](B,A);
until has(B[vv,vv],[vertset]);
i;
end proc:

## disjoint cycles...

@mmcdara I meant only that you find other cycles in this way. It is well known in graph theory that the ringsum of cycles gives other cycles or disjoint unions of cycles, but the disjoint unions can be easily detected. So then you get the algorithm that I think you now have (this is similar to the "cut" case I did earlier in a blog here.) You can also represent the cycles as vectors with addition mod 2, just as in the cuts case.

## combining cycles...

 > restart:
 > with(GraphTheory):
 > C1 := {seq({i, i+1}, i=1..6), {7, 1}}: C2 := {{1, 8}, {8, 3}, {8, 6}}: G := Graph(C1 union C2): DrawGraph(G, style=planar); cb:=CycleBasis(G);

How to find [3, 4, 5, 6, 8]? Considered as sets of edges, the symmetric difference (or "ringsum") operation combines cycles into other cycles  - it kills common edges.

Actually finding cycles or counting all of them is nontrivial. Here combining all three cycles works.

 > cycles:=map(x->Edges(InducedSubgraph(G,x)),cb);

 > symmdiff(cycles[1],cycles[3],cycles[2]);

 >