Message Boards Message Boards

10
|
3309 Views
|
255 Replies
|
215 Total Likes
View groups...
Share
Share this post:
GROUPS:

[WSG24] Daily Study Group: Programming Proficiency

Posted 1 month ago

A Wolfram U Daily Study Group previewing our upcoming Programming Proficiency course sequence begins on Monday, January 29, 2024. The study group will run for ten days through February 9, and each day will run from 11AM to noon CDT.

Join me, @Abrita Chakravarty and a cohort of fellow enthusiasts to build a strong foundation for any and all sorts of Wolfram Language programming that you'll do in the future. We'll cover everything from syntax, definitions, and the underlying structure of expressions to efficient coding, working with various data structures, and even developing packages.

This study group will cover material from our Programming Fundamentals and Practical Programming courses, as well as provide attendees a first look at Programming and Development, the upcoming third and final course in the Programming Proficiency course sequence. Our intent is to provide a setting for this material which not only reaps the benefits of our Daily Study Groups'... well, group nature, but also spreads this material out over two weeks for those who cannot commit to the three-hour blocks required by these courses in their natural habitat.

This study groups aims to get you up and running with Wolfram Language, and as such no prior Wolfram Language or programming experience is necessary.

REGISTER HERE.

We look forward to seeing you there!

enter image description here

POSTED BY: Arben Kalziqi
255 Replies
Posted 5 days ago

...

POSTED BY: lara wag
Posted 5 days ago

Suppose there is an external database or other data source. Unfortunately, in this external data source, the keys are in lower case with underscores ("snake_case"), e.g. company_name. To work properly in Wolfram Language, the keys must be in camel case, e.g. companyName.

Here is an example that works on a List of Associations:

AssociationThread[
   StringReplace[Keys[#], 
     MapApply[Rule, 
      Transpose@{"_" <> # & /@ Alphabet[], 
        ToUpperCase[Alphabet[]]}]] -> Values[#]] & /@ data

To be honest, from my perspective it looks ugly, especially the "Transpose" part. Any ideas on how to make this transformation more concise?

... or is there a built-in function for this that I don't know about? I saw this resource function https://resources.wolframcloud.com/FunctionRepository/resources/ToCamelCase/, but I wasn't able to make it run in this "key of association" problem.

Notebook with sample data attached.

POSTED BY: lara wag

Hi Lara—keys in an association can be basically whatever you want, and certainly be in the form of "company_name" for example. If you need to access them via "slot" notation, you can just wrap them in quotes:

In[280]:= #"company_name" &@<|"company_name" -> 2|>

Out[280]= 2
POSTED BY: Arben Kalziqi
Posted 5 days ago

Thank you, Arben, for your super-fast reply.

Interesting - so it works with quotation marks. - Thank you!

POSTED BY: lara wag

Hi Lara,

An easier way to rename the keys is to use KeyMap.

data // Map[
  KeyMap[StringReplace[{"_id" -> "ID", 
                        "id" -> "ID",
                        "_" ~~ c : LetterCharacter :> ToUpperCase@c}]]]
POSTED BY: Rohit Namjoshi
Posted 5 days ago

Thank you very much, R, impressive! I was looking for something like that.

POSTED BY: lara wag

Hi Arben;

I remember you covering in one of the lectures a technique of applying MapAll (/.) before evaluating the expression as opposed to after the expression is evaluated. However, I cannot remember the way you formatted the function. Can you please show me one more time? The example below shows the values being assigned after the function is evaluated, which is not what I want. What I want are the values of Sin[t], Cos[t], Tan[t] to be assigned to x, y, z before any other functions are evaluated.

Thanks,

Mitch Sandlin

D[Log[x^2 + y^2 + z^2], t] /. {x -> Sin[t], y -> Cos[t], z -> Tan[t]}
POSTED BY: Mitchell Sandlin

I think you just do exactly what you said you want to do, i.e. assign the variables before you take the derivative:

D[
Log[x^2 + y^2 + z^2] /. {x -> Sin[t], y -> Cos[t], z -> Tan[t]}
, t]

Or even before you take the Log, but I think that gives you the same answer:

D[Log[(x^2 + y^2 + z^2) /. {x -> Sin[t], y -> Cos[t], z -> Tan[t]}],
  t]
POSTED BY: Carl Hahn

Hi Mitchell

/. is ReplaceAll, not MapAll. I don't recall what Arben showed but here are a couple of ways

Unevaluated[D[Log[x^2 + y^2 + z^2], t]] /. {x -> Sin[t], y -> Cos[t], z -> Tan[t]}

Hold[D[Log[x^2 + y^2 + z^2], t]] /. {x -> Sin[t], y -> Cos[t], z -> Tan[t]} // ReleaseHold

(* (2 Sec[t]^2 Tan[t])/(Cos[t]^2 + Sin[t]^2 + Tan[t]^2) *)
POSTED BY: Rohit Namjoshi

Take Rohit's answer, but also note that if you were to write x'[t] and so on—that is, explicitly note the time dependence—D will take those derivatives symbolically and you can plug in values for the time-dependent functions after the fact, at which point the derivatives will be evaluated.

POSTED BY: Arben Kalziqi

Arben, I don't think I understand what you just said (a rare thing...). How would you re-write the expression?

I liked the elegance of the "Hold" and "Release Hold" solution, but only because it's explicit. However, I do get the same answer by using ReplaceAll within the brackets of the Derivative forcing it to happen before the derivative is taken. I've noticed in other people's examples that you can stick the /. operation all over the place. What is wrong with that?

(my own answer would be that if you are writing longer code, it gets hard to read and understand - I'm just asking a more generic question about WL grammar rules) Carl

POSTED BY: Carl Hahn

I've noticed in other people's examples that you can stick the /. operation all over the place. What is wrong with that? (my own answer would be that if you are writing longer code, it gets hard to read and understand - I'm just asking a more generic question about WL grammar rules) Carl

My suggestion is to use the standard functional call (ReplaceAll[], etc.) until you thoroughly understand them. You should always -- always -- be able to see and say the long form when the shortcut is being used. IMHO, it's a big problem to use shortcuts if you don't always have the formal name of the function call on the tip of your tongue. Note: even things like _x have a standard form: Blank[x]. Computers have the ability to expand any shortcut within a microsecond; we should be ability to translate either way with a similar amount of minimal computational overhead.

You want to be able to rattle off a spell with the ease of Hermione Granger and avoid the clumsiness of Neville Longbottom. You should have no "lost in translation" moments between a shortcut and its normal form.

I kinda wish that the Notebook editor would have a means of flipping something to its normal form (and vice versa). I also wish that the Help documentation would always show both forms on examples; it tends to be prejudiced towards the shortcuts. I like to verbalize the normal form when I look up something in the docs.

POSTED BY: Phil Earnhardt
Posted 5 days ago

That's a fine and helpful tip for the newbies to the Language. I'm having to constantly look up and flip over to several views or points. The Docs but There are many "points" in the docs to look at. I have to reference a LOT. So that's one thing I'm learning. It's not enough just to read one part.

I often remind myself. I'm doing it wrong! What am I missing? What can I not see?

Does anyone have any experience with Reeturn[] I'm not able to use it on TraceDialog. With this error message.

"TraceDialog::dgbgn: Entering Dialog; use Return[] to exit." I didn't get a dialog and my process was stuck running. I had to close the window to get it to stop.

Cheers.

POSTED BY: z w
Posted 10 days ago

Will there be another one of these classes?

POSTED BY: Paul Nielan
Posted 10 days ago

Will there be another one of these classes?

POSTED BY: Paul Nielan
Posted 11 days ago

I'm having problems understanding number three which works with Set Delayed Rule and Blank.

I couldn't catch on C++ a long time ago in college. Maybe that's why I don't understand this concept. Object orientated programming. My problem seems that there's too much overlap in definitions. There's no similarly to compare it to. The concept is Invisible.

There's a few things happening with the blank, and the "f" and the "x" those are all condensed things or overlapping definitions. Left to right replacement. Got that. what is "f" and "x" or x or x you could call them "Head" or a function. of the [ ]. I'm struggling to find an explanation of what x or x is Now I do understand that is is just a blank to be filled in but the x or f is a distraction. why not just _ without f or x that make more sense.

Now I tried to make this work and nope. nothing works. Is it because of the Delayed rule? That's a new idea. I guess I haven't tested that out yet. changing :> to -> instead. I can try that next. I don't understand what to do to get the replacement happening it seems that it should be just happening if there are blanks in the right place but maybe it's because of the Delayed rule. I tried changing the delay to a rule and it's the same. I used Trace. With Trace I just get {} and without Trace I get the same out as I put in f[1,2,3] I don't know if the rule is even working or able to work on f[1,2,3] that's my problem I don't see how the problem is applied to f[1,2,3] it seems it is not.

POSTED BY: z w
Posted 10 days ago

I found Richard J. Gaylord's video on youtube. It's a great video and I saw it a while back. The first five minutes of the video or really the first minute of the video when he starts his lecture has got me into the invisible part and it's a great help to understand the structure of wolfram language. I hope to find and learn how to read the Docs better.

I'm doing FullForm the rhs of number three which is what I was talking about. It's been helping so far. I still have to learn the Pattern. Like I said it's confusing how the new vocabulary is used with seeming overlapping meanings. This first minute of the video has been helpful to find what to look for.

Head and what follows? and how WF evaluates it maybe old news for some of if you. For me who I haven't been using the language for a long time regularly it's a big help. I'm not done yet.

POSTED BY: z w
Posted 10 days ago

Thanks for the useful reference. Fills in some of the blanks in Arden's excellent lectures. I always like several points of view.

POSTED BY: Steven Brawer

This is a nice talk! Glad to see that I've naturally settled on many of the same explanations as Richard gives here :)

POSTED BY: Arben Kalziqi
Posted 8 days ago

I worked on a exercise to from EIWL which was just adding up a list and I wanted to do it with Plus, Range. I failed and spent a hour learning. Then came back to it.

Recap. I was working on trying to use a symbol to do the adding or multiplying with @@ I could not get it to work. I could not figure out what was happening. I tried a lot of things. Nothing seemed to work. I looked up Trace, TreeForm, and a whatever I came across. I played around with the documentation changing the code around.

I figured out how to do it, after my nap. Checking with TreeForm told me the "path" of the code that I could not see. Checking the documentation on how to properly write it over and over. I could see that Plus was not getting worked on the List. So I knew I wrote it wrong.

The hour of work was not wasted. From that hour of work. That is how I got the code to be "visible". I worked with TreeForm and the documentation trying out Map, ThreadMap, Funny because I was using Apply in the first place I just wrote it wrong.

I found a you-tube video on Lists that was helpful. I also read some tutorials on how to properly write wolfram code. I read the Filled in Notebooks, and whatever I came across. So it was a bunch of hopping around sources then a long break and back to finally finding the correct way to write it. It helps that I realize that I'm trying to write it the way I think it works and that is wrong. I need to find how it is supposed to be written.

Merry coding to everyone.

POSTED BY: z w

Hi Arben;

As an aside, I came across something the other day that I did not understand but figured you would.

I understand what a Derivative (D) and an Implicit Derivative (ImplicitD) are, but what in the world is a Total Derivative (Dt). In all my years of math, I just came across this thing called a Total Derivative and hoped you could shed some light.

Thanks,

Mitch Sandlin

POSTED BY: Mitchell Sandlin
Posted 11 days ago

Hey Mitch! I also remember coming to this comparatively late in my math career (though frankly I'm sure it was in our diff eq class and I missed it because I was boooooored). As is indicated by Steve, probably the easiest inroad to the idea of the total derivative is the chain rule. To that end, check out the corresponding lesson from our multivariable calculus MOOC (including lesson notebook, lecture video, and exercises with solutions)—it's lesson 15 here.

POSTED BY: Arben Kalziqi

On the L1 exam, do I take a list shown as {1, 2, 3, a, b, c} verbatim or am I to interpret the list as {1, 2, 3, "a", "b", "c"}? I wasn't sure since the color coding as done in Mathematica didn't carry over to the exam.

POSTED BY: David Snyder

Definitely verbatim. If you think that there is an error, be sure to tell Arben :-)

POSTED BY: Lori Johnson

(confirming here for, well, official confirmation.)

POSTED BY: Arben Kalziqi
Posted 14 days ago

I have a question about pattern matching.

  1. Cases[{1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0}, {0, 1, 0}] This returns empty. I know why :
  2. Cases[{1, 1, 0, 1, 1, 0, 1, 0, 0, 1, {0, 1, 0}, 1, 0, 0}, {0, 1, 0}] This returns {0,1,0}

So the List delimiters {} make that example 1 does not work.

I tried Cases[{1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0}, {_ _ , 0, 1, 0, _ _ }]
Code should show { underscore 3x , 0,1,0, underscore 3x } unfortunately but comes out different in the post (only 2 underscores are shown). This also does not give a correct result but {}. I was surprised that this is wrong :-)

How should I approach example one, so that I get the 4 times 0,1,0 as a result? And how do I get the starting positions of each 0,1,0 ? (so here : {6,9,11,13}

POSTED BY: B. Cornas
Posted 14 days ago

Use Partition. It can be done in one instruction, but to make it clearer, I break it down:

lst = {1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0};

par = Partition[lst, 3, 1]

Cases[par, {0, 1, 0}]
POSTED BY: Gerald Dorfman
Posted 14 days ago

Thanks Gerald, I understand your way. I see that the '1' in the Partition[lst, 3, 1] is needed. I also need to get the positions and can get those by Position[par,{0,1,0}]. The result is correct. Your way works also good if the list starts or ends with the wanted pattern.

In a broader context, I need to test many more 'regularities'. Imagine the lst = {1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0} is a rhythm where 1 stands for a hit and 0 for a silence. I want to get all the regularities from this rhythm line. So I would need to test also parts with length 2, length 4, etc. And I need to do it fast (testing many rhythms). So maybe there is a way to avoid the partitioning, which would have to be different for different lengths of search lists.

This checks for 'repetitions'. How could I test for mirror symmetry? E.g. {0,0,0,1,0,1,1,0,1}. here 1,0,1 is a symmetry as well as 1,0,1,1,0,1 How could I test for Permutations of the pattern? E.g. {1,0,1,x,x,x,x 0,1,1,x,x,x,x,1,1,0}. here are 3 permutations of {1,0,1} present. How to detect them?

POSTED BY: B. Cornas
Posted 14 days ago

In attached file Symmetries.nb , I've written and executed a module to find the symmetries you are interested in and a function to count the number of subsequences in an ordered list of length at least 2.

The module creates a random list of zeros and ones of length at least 2, finds all its ordered subsequences of length at least 2, and lists all its symmetric subsequences. I assume that subsequences of length 1 are of no interest because they are trivially symmetric.

The simple function counts the number of subsequences of length 2 or more from a list of length at least 2. The code uses the function to print a table of the counts for lists of length 2 through 15.

Although I compute the number of subsequences as a sum, it's easy to derive the formula by just evaluating the sum. Given a list (i.e., an ordered list) of length n, the number of subsequences of it of length k is just the number of leftmost positions of sequences of length k, namely n-(k-1) = (n+1) - k. Now, sum for k = 2 to n. Since (n+1) is a constant, the sum of the first term is (n-1)(n+1) = n^2 - 1. The sum of the second term is just 1 less than the sum of the first n integers, namely n(n+1)/2 - 1 = (n^2)/2 + n/2 -1. So the number of subsequences of length at least 2 of a list of length n is (n^2 - 1) - ((n^2)/2 + n/2 -1) = ((n^2)/2 - n/2 = n(n-1)/2. So, instead of using the sum to define the function numSequences , one could define it as numSequences[n_Integer /; n >= 2] := n(n-1)/2 . I used the sum just to make the code easy to understand.

Attachments:
POSTED BY: Gerald Dorfman
Posted 13 days ago

Hi Gerald, thanks for your help. I just downloaded your example Nb and will look into it. I'll come back on it later.

POSTED BY: B. Cornas
Posted 13 days ago

I worked through your Nb. Thanks for the work you've done. It works well and I learned a thing or two, which I can apply on other places in my project.

Really appreciate your help, as well as Rohit's.

POSTED BY: B. Cornas
Posted 13 days ago

Here are a couple addenda to the Symmetries.nb file and comments I provided:

(1) A quick derivation for the formula for the number of (ordered) subsequences in an n-sequence (i.e., an ordered sequence of length n): Call the n-sequence "seq", and number its positions from left to right 1, 2, ..., n. The subsequences are uniquely defined by their leftmost and rightmost positions. Since we want subsequences of length at least 2, the choices for the rightmost position are 2, ..., n. If k is the choice for the rightmost position, then the choices for the leftmost position are 1, 2, ..., k-1, so there are k-1 choices for the leftmost position and hence k-1 subsequences with rightmost position k. So, the number of subsequences in an n-sequence is the sum of (k-1) for k = 2, 3, ..., n. That's the same as the sum of the integers from 1 to (n-1), which is just n(n-1)/2. (The formula for the sum of the first m integers is well known. It's just m(m+1)/2.)

(2) Instead of using Cases in file Symmetries.nb, I could have used Select:

    Select[subsequences, (#===Reverse[#])&];

I used Cases to show how to use a pattern, which can also be used for Position.

POSTED BY: Gerald Dorfman
Posted 12 days ago

I am happy to see your explanation for the derivation for the formula for the number of (ordered) subsequences in an n-sequence. Very helpful. I tried Select i.s.o Cases and that works fine as well. I guess that you put the parenthesis around # === Reverse[#] in Select[subSequences, (# === Reverse[#]) &]; for clarity. It also works without them.

Thanks again , Gerald

POSTED BY: B. Cornas
Posted 12 days ago

Yes. I put the parentheses around the pure function for clarity. Doing stuff like that was recommended in class. For myself, given how simple that pure function is, I would not have bothered.

POSTED BY: Gerald Dorfman
Posted 12 days ago

I thought so, but a useful practice :-)

POSTED BY: B. Cornas

one quick note here: parentheses are still good for clarity, but we did—in version 13.x for some value of x—introduce something to help here. namely, when you type & after a pure function, it will quickly highlight the function it's "closing" so you can be sure that you have things grouped correctly. (the common case here is when doing something like ColorFunction->#1^2&—you need the parentheses after the -> because otherwise it thinks the pure function to be closed is ColorFunction->#1^2 rather than just #1^2.)

POSTED BY: Arben Kalziqi
Posted 11 days ago

I have not run any benchmarks but I suspect that using the built-in PalindromeQ may be faster than # === Reverse[#] &.

POSTED BY: Rohit Namjoshi
Posted 11 days ago

Hi Rohit,

that was my idea as well and I wanted to do some timing tests as soon as I had time. Also the Option 'Overlap' we talked about earlier is very useful for my project.

But the extended explanation of Gerald helped me in another way. I am pretty new to Wolfram language and still have to adapt from Procedural programming, which takes quite a paradigm shift.

POSTED BY: B. Cornas
Posted 14 days ago

Use the Sequence* family of functions

list = {1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0}

SequenceCases[list, {0, 1, 0}, Overlaps -> True]

SequencePosition[list, {0, 1, 0}]

Overlaps -> True is the default for SequencePosition which is a little inconsistent

POSTED BY: Rohit Namjoshi
Posted 14 days ago

Great Rohit, this works very well. Thanks.

In which sense is Overlaps -> True inconsistent? I saw in the docs, that SequencePosition has the same Overlaps option. Is it also inconsistent there?

Would you also have some suggestions for the following :

This checks for 'repetitions'. How could I test for mirror symmetry? E.g. {0,0,0,1,0,1,1,0,1}. here 1,0,1 is a symmetry as well as 1,0,1,1,0,1 How could I test for Permutations of the pattern? E.g. {1,0,1,x,x,x,x 0,1,1,x,x,x,x,1,1,0}. here are 3 permutations of {1,0,1} present. How to detect them?

POSTED BY: B. Cornas
Posted 14 days ago

Hi B.

In which sense is Overlaps -> True inconsistent? I saw in the docs, that SequencePosition has the same Overlaps option. Is it also inconsistent there?

What I meant is that the default value of Overlaps is True for SequencePosition and False for SequenceCases. That seems inconsistent to me.

For symmetry something like this?

list = {0, 0, 0, 1, 0, 1, 1, 0, 1}
Subsequences[list, {3, Length@list}] // Select[PalindromeQ]

For permutations generate all of them and test each with SequencePosition?

perms = Permutations[{1, 0, 1}]
list = {1,0,1,x,x,x,x 0,1,1,x,x,x,x,1,1,0}
SequencePosition[list, #] & /@ perms
POSTED BY: Updating Name
Posted 13 days ago

Thanks Rohit, i get the 'inconsistency' and I agree.

Your solutions for Symmetry and Permutations work fine and I can extend on them :-)

POSTED BY: B. Cornas
Posted 8 days ago

Hi Rohit,

I wanted to take your idea a little further, more general, but I run into a snag I do not understand. SequenceCases[pattern1, {0, 1, 0}, Overlaps -> False] from your previous post. This works great :-)

But now to find more general patterns : list={0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1} patternToFind = {x, y, x_} SequenceCases[list, patternToFind, Overlaps -> False]

I get {{1, 1, 1}, {1, 0, 1}, {1, 0, 1}} as result.

Why is the [1,1,1} there? I specified the first and third to be the same, but the second element to be different. I expected to get {1,0,1} and {0,1,0}. The result also misses the {0,1,0}.

Any good ideas?

POSTED BY: Updating Name

Hi B.

In a pattern with a symbol, the symbol is what the match is set to. So {x_, y_, x_} matches something, x is set to that thing, followed by something, y is set to that thing, etc. The fact that the symbol is different does not mean the match has to be different.

MatchQ[{1, 1, 1}, {a_, b_, a_}]
(* True *)

You need to use Condition to ensure they are different

MatchQ[{1, 1, 1}, {a_, b_, a_} /; b != a]
(* False *)

The missing ones are because of Overlaps -> False

SequenceCases[list, {x_, y_, x_} /; x != y, Overlaps -> True]
(* {{1, 0, 1}, {0, 1, 0}, {1, 0, 1}, {1, 0, 1}, {0, 1, 0}} *)

The matching positions

SequencePosition[list, {x_, y_, x_} /; x != y, Overlaps -> True]
(* {{6, 8}, {7, 9}, {8, 10}, {11, 13}, {12, 14}} *)
POSTED BY: Rohit Namjoshi
Posted 8 days ago

Great Rohit, thanks.

I had understood that {x,y,x} was different from {x,x,x} as a pattern .

I had the 'Overlaps -> True' first, but as I did not have x != y , I got about way too much solutions.

Now it works fine :-)

Best , Bert

POSTED BY: B. Cornas

Hi Bert,

They are not the same

MatchQ[{1, 2, 1}, {x_, x_, x_}]
(* False *)

MatchQ[{1, 2, 1}, {x_, y_, x_}]
(* True *)

The first pattern specifies that all elements must be the same. The second specifies that the first and third elements are the same. The second element can be anything, including the same as the first and third.

MatchQ[{1, 1, 1}, {x_, y_, x_}]
(* True *)
POSTED BY: Rohit Namjoshi

Precisely! When I talk about pattern matching, I always talk about x_ as "something—call it x" for exactly this reason.

POSTED BY: Arben Kalziqi
Posted 6 days ago

Rohit & Arben, I get it. Great help. Cheers , Bert

POSTED BY: B. Cornas
Posted 14 days ago

Is the 5th question in the level 1 exam :-

"Beginning with data = {{15000, , 89000,, ............"

correct/valid ?

POSTED BY: Doug Beveridge
Posted 14 days ago

Ok , it is correct

POSTED BY: Doug Beveridge
Posted 14 days ago

Questions are randomly (actually, pseudorandomly) selected from a pool; the odds that any person would have the same 5th question are rather low.

I had a question on my L1 quiz where there were 3 possible answers, plus "all of the above". It turned out that 2 of the 3 were giving the correct response and one was giving a different response; none of the answers could possibly be right. I was running my quiz notebook off of the Wolfram Cloud; that appears to be the reason for the one buggy response. I answered the question as if the function was behaving correctly. I sent an e-mail to wolfram-u@wolfram.com noting the bad behavior and filed it as a bug in Mathematica.

Here are my rules in taking a Wolfram quiz or cert test. It took me a while to figure these out...

  1. Try as hard as you can on every single question.

  2. Realize that you may still get some questions wrong no matter what you do or know. Don't sweat it.

  3. Appreciate the difficulty in authoring a perfect quiz. There may be bugs, bugs may creep in over time, and you may get some "no win" questions. Flag questions you're pretty sure are buggy in e-mail to Wolfram U. Remember rules 1 and 2, and have fun.

POSTED BY: Phil Earnhardt

Thanks Phil—no kidding on authoring assessments! It's difficult to write questions of the correct difficulty, the right amount of "almost, but not exactly, and wrong in an instructive way" answers, and account for possible bugs, input types, edge cases, and so on. Still, we're always looking to improve and always appreciate any bug reports or suggestions that come our way.

POSTED BY: Arben Kalziqi
Posted 15 days ago

Hi Arben,

I have another question about Manipulate and it ties in with my questions from 3 days ago about 'Stepping back' to previous settings in Manipulate.

One has to be quite careful not to create a loop in a Manipulate construct. E,g. a= a+2 gives already a loop. If done like aNew = a+ 2, then it's ok. More 'funny things' might happen in a more complex Manipulate construction.

My question is : How is the order of the calculations in a Manipulate? Does it go from top to bottom, like line for line (and left to right)? Always? What if I change a parameter (slider) whose appearance is only after 20 lines of code? Is still all the code run from the top, or does the re-calculation start where the changed value first appears (e.g. line 20)?

How can I step through the code and watch the changing variables, like in 'Step-Debug'? Thanks a lot,

Bert

POSTED BY: B. Cornas
Posted 11 days ago

Hi Arben,

I would really appreciate if you could shed some light on these questions of mine. I hope you find the time for it :-)

I read through both "Dynamic & Manipulate Notes" and the "Advanced Dynamic & Manipulate Notes". I could not find anything about the order of execution of the lines of code or step Debug in a Manipulate construct.

Thanks a lot, Beat

POSTED BY: B. Cornas

Hey Bert! I didn't know the answer to this one off the top of my head. After some investigation, I have to say "it's complicated."

From the Advanced Dynamic Functionality Tutorial:

Dynamic expressions can be nested, and the system takes great care to update them only when necessary. Particularly when the contents of a Dynamic contain further interactive elements, it is important to keep track of what will stay static and what will update, when a given variable is changed.

It seems as if for any given dynamic expression, there's a step which involves "tracking down" what pieces of the expression can/will change when certain dynamic variables are updated, and it's those pieces which end up being reevaluated.

POSTED BY: Arben Kalziqi
Posted 10 days ago

Thanks Arben, for your help and work.

It certainly is quite complicated and I started wondering after I found that the code inside Manipulate is not necessarily executed from top to bottom. It is getting even more complicated if there are Dynamic functions explicit withing the Manipulate. Maybe I can come up with some Flags that get set when some line of code is re-executed. I'll have to try.

I will read through the Advanced manipulate and Dynamic paper again :-)

Best, Bert

POSTED BY: B. Cornas

Part of the issue here—and I think why you probably didn't think that the quoted section was useful when you first read it—is that Manipulate is making its own DynamicModule under the hood. This means that even if you're not typing Dynamic[x], the fact that you have (say) {x,1,10} as the second argument to Manipulate means that the constructed DynamicModule does have Dynamic[x] in there—which is why the quoted section is actually relevant, even if you aren't personally typing Dynamic[x].

POSTED BY: Arben Kalziqi
Posted 10 days ago

Very good point, Arben :-)

POSTED BY: B. Cornas

I am having email problems. How do I join the class without today's link? Sorry about this!

POSTED BY: Paul Tikotin

@Paul Tikotin, we'll send your join link to your email, or you can contact us at wolfram-u@wolfram.com to provide a different address, if you're having trouble with gmail. You can also go to the webinar page to register and receive a join link using a different email address. Email communication of some sort will be needed.

POSTED BY: Jamie Peterson

I think I have just sorted the problem,...Thank you!

POSTED BY: Paul Tikotin
Posted 16 days ago

I am running Mathematica version 14 under Windows 11 on an HP Envy laptop. To compare AbsoluteTiming for 3 alternative instructions to do the same thing, I wrote the following code and was surprised to see that "Power" was not quite the fastest. (Timing[...] just showed 0. for all 3 instructions.)
I'd appreciate an analysis of my findings.

In[104]:= listOfAssoc=Association@@@({"a"->#[[1]],"b"->#[[2]]}&/@Partition[Range[1000],2]);
tbl=listOfAssoc[[;;2]]

Out[105]= {<|a->1,b->2|>,<|a->3,b->4|>}

In[106]:= First@AbsoluteTiming[Power@@@listOfAssoc]

First@AbsoluteTiming[#a^#b&/@listOfAssoc]

First@AbsoluteTiming[#[[1]]^#[[2]]&/@listOfAssoc]

Out[106]= 0.0118669

Out[107]= 0.0107371

Out[108]= 0.0082883
POSTED BY: Gerald Dorfman

As we're fleshing out project ideas for the level 2 certification, is there someone we can meet with to make sure we're on the right track?

POSTED BY: Kari Grafton
Posted 16 days ago

How about a separate Wolfram Community discussion to speculate/brainstorm about L2 cert projects? Anyone can create a new discussion, but it might be good to have the "seal of approval" if @Arben Kalziqi or @Jamie Peterson were to create it. :)

I am looking at a Wolfram Examples project showing muscle co-activation of hand flexors/extensors, arm flexors/extensors, and arm pronators/supinators. The beautiful Anatomy package has the ability to do color illustrations; I can graphically show the muscles involved in particular co-activations. Apparently, the Anatomy package also has identifiers for the antagonist pairs; I need to investigate that. Apologies if those words make no sense; it's better in pictures.

POSTED BY: Phil Earnhardt

I really like this idea! @Arben Kalziqi, @Jamie Peterson, can we make this happen?

POSTED BY: Kari Grafton

While I (hopefully clearly) do enjoy answering everybody's questions here, for something as involved as the Level 2 projects I'm afraid it's not really feasible from a time/involvement perspective. Like Jamie said, please do take advantage of office hours, and we may well offer more things like this in the future. (Actually, typing that reminds me that we have something in the cards for like, an "interesting example + office hour Fridays" series... we'll see if that comes to fruition!)

POSTED BY: Arben Kalziqi
Posted 16 days ago

While I (hopefully clearly) do enjoy answering everybody's questions here, for something as involved as the Level 2 projects I'm afraid it's not really feasible from a time/involvement perspective.

Whoa! While I can't speak for @Kari Grafton, my intent was never to turn this proposed discussion group into a place for Wolfram staffers to guide us through any steps of the L2 project process. My intention was to have an informal conversation between participants in the process. In what I'm visualizing, it's probably the case that WR staff participation in the discussion would be counterproductive.

As proposed, the L2 cert process is a solitary interaction between a developer and Wolfram Research. The process is isolated; there's no sense of community in that process. A successful course (like this one) nurtures a sense of community in the participants; that's what I was looking for in a L2 Wolfram Community discussion.

Maybe the discussion group is about encouraging participants to create a project worthy of putting in one of the designated repositories. That project may or may not be sufficient for a L2 certification; that's not really important. I think this is very different from what Arben and Jamie were hearing when they reacted to this discussion.

What is clear: I need to choose words carefully for the first message of the discussion group. Let people know this has nothing to do with anything official that WR is doing. Let them know it's about community. The discussion is more like Stephen Covey's idea in The 8th Habit: Find Your Voice, and Inspire Others to Find Theirs

POSTED BY: Phil Earnhardt

In that case, I support y'all wholeheartedly (imagine I could use emojis here and added a :sweat_smile: at the end there, okay).

POSTED BY: Arben Kalziqi

My best suggestion is to use today's Study Group survey to request your registration at the March 1 instructor office hours, which will also be available as part of the upcoming Programming Proficiency course sequence. Register for the course sequence here.

POSTED BY: Jamie Peterson

Great, thank you! I did request registration for the office hours. And I agree that a L2 discussion board geared towards the participants is a great idea.

POSTED BY: Kari Grafton

Hi Jamie, Cassidy, Abrita, Arben!

Thank you for all your hard work that goes into making these study groups enjoyable. [big smiley]

I enjoyed the fill-in-the-blank format of the Level 1 quiz. Keep that coming. The Level 2 Certificate is on my agenda (the Nutrition Report looks interesting) as are almost every new webinar and WSG. Artisinal Calculus, why, yes, I think I will!

I'm sleeping in today but I will see y'all soon. Stay safe. Stay healthy. Lori

POSTED BY: Lori Johnson

Same! I can't get enough of these webinars and try to do every one that looks like it's even remotely related to something I might use. Or just looks particularly interesting.

POSTED BY: Kari Grafton

Hi Kari!

Nice to meet you! Absolutely. My goal is to learn at least one new piece of creative programming each time, be reminded of a command I may have forgotten, etc. I am seldom disappointed :D

Do you collect session notebooks, too? They're like conference handouts. There are always "goodies" inside.

POSTED BY: Lori Johnson

Thanks Lori! We always enjoy having you with us. Hopefully you enjoy the review recording and notebook if you'd like to peruse them after sleeping in!

POSTED BY: Arben Kalziqi
Posted 16 days ago

Aww, that's a very nice thing to say. Thank you, Arben!!!

Will do! Have a fun weekend :D

POSTED BY: Updating Name

I am trying to rid my code of Do loops as suggested in the training, but I am having some difficulty in getting the simple example in my notebook to work. It is not clear to me how to get the names to cycle through the example. I have several sources of data each with a key value that I am trying to combine into one variable. This is how I am doing it now. I believe if I could figure out how to do the simple example in my attached notebook, I could make the below work.

Do[bE1defgrad[[i]] = 
   Map[Append[#, Select[sEDNH, MemberQ[#, bE1[[i]]] &][[1]][[3]]] &, 
    Map[Append[#, 
       Select[pressure, MemberQ[#, bE1[[i]]] &][[1]][[2]]] &, 
     Select[defGrad, MemberQ[#, bE1[[i]]] &]]];,
 {i, 1, bE1len}]

POSTED BY: Philip Van Riper
Posted 16 days ago

Hi Philip,

The code you posted is incomplete, there are several symbols that are not defined sEDNH, pressure, defGrad, ....

I also don't understand what you are trying to accomplish with combined. It just adds an additional level of nesting to dgrad because names includes all of the elements in dgrad

dgrad == First /@ combined
(* True *)

If you just want to pick out the matches to names here is a functional way to do it. There is no need to initialize combined

combined = Select[dgrad, MemberQ[names, First@#] &]
POSTED BY: Rohit Namjoshi

Hey Philip—agree with Rohit here; I'm not sure what you're trying to do exactly. If you could upload a version of the notebook where you've defined everything that you're using and where you've explained what each "step" is supposed to do (like by saying "i have [input], and it does [xyz], resulting in [output]"), I'm sure I'd be able to help.

POSTED BY: Arben Kalziqi

Thanks for the feedback. I am reading several files into my notebook and I ended up simplifying it too much without providing the needed context. Hopefully the attached notebook rectifies this. I basically have three lists that contain data keyed to a list of names. I wish to combine all of the data into one list, but only for the items in the list names.

My background is Fortran, so I instantly think of loops, however the Wolfram language intrigues me and I really want to use it effectively. Phil

POSTED BY: Philip Van Riper
Posted 13 days ago

Hi Philip,

I have modified your notebook and added a solution to the end. Light green cells are ones I added.

Attachments:
POSTED BY: Rohit Namjoshi

Rohit, Thanks for the solution. It looks much better that the Do loop and gives me new avenues to explore. Phil

POSTED BY: Philip Van Riper
Posted 17 days ago

package question

All examples of creating a package (after foo::usage=...;bar::usage=...., etc) use

Begin["`Private`"]

and then function bodies follow. Does the word "Private" have some particular significance. What would be the problem with using some other word like

Begin["`NotPrivateAtAll`"]

How is this designation actually used?

POSTED BY: Steven Brawer
Posted 17 days ago

Does the word "Private" have some particular significance. What would be the problem with using some other word like [...]

"Private" has no significance. If you go to the Wolfram Language Documentation for Begin, you'll see the examples there use "MyContext`". "Private" is not a keyword in the WL, but [IMHO] the fact that it is a keyword in many programming languages means it should probably be avoided in examples in Wolfram courses. OTOH, "MyContext" is definitely un-keywordy.

It's really helpful to use the Wolfram Language Documentation as the first place to go with questions like this. I don't think that Arben has emphasized the wonderful Wolfram documentation in this course. Docs are available on the web; they are also typically installed in a Mathematica install and can be accessed through a Mathematica window. Carpe documenta!

POSTED BY: Phil Earnhardt
Posted 16 days ago

Thank you. Mathematica documentation could be called "minimal".

Consider the "Begin" documentation. For example, under "applications" there is this for BeginPackage: "Make symbols used for package function definitions private, reducing the possibility for conflict:" Fine. What exactly is the problem with saying: "this defines a namespace" (or at east say Context = namespace)? Unless it doesn't actually define a namespace (or it does, but with lots of caveats), and if not, that should definitely be explained.

Moreover, "Private" is used in the one single "application" section example but not in any examples of the "examples" section. In addition, without a specific statement that "Private" is not special, it is unclear whether using it might have some unanticipated side effect. (In Mathematica, unanticipated side effects are anticipated.) Absence of a comment is not documentation, especially these days when everyone is very busy. If you google "Mathematica packages", there is hardly anything there (or hardly anything simple).

Mathematica is a wonderful and very useful but very complicated system, and the paltry number of examples for such an important subject as Packages means hours wasted trying to figure simple things out.

Here's another interesting thing that is hardly obvious (at least to me, and is probably buried somewhere in a document). Suppose you define G = {x1^n, x2^m} in a program (x1,x2, unassigned symbols) and you want to differentiate G (with respect to x1) in a function someName[G] := ... which is located in a package, where the function body contains D[G[[1]],x1]. As far as I can tell, unless you define the package function as someName[G, x1,x2] and call it from the program as someName[G,x1,x2], it will NOT work. How does the engine know to link the x1,x2 in the call with the x1,x2 in G? This is hardly obvious. There is presumably a whole world of Mathematica-namespace concepts underneath this, which it would be very nice to at least glimpse.

POSTED BY: Steven Brawer
Posted 16 days ago

If there are bugs/shortcomings in the documentation, you can file a support ticket with Wolfram.

As far as Private not being a keyword, I just looked up that word in the documentation. Simple. "Private" the String is used as an option in some functions, but that doesn't leak out and affect other things. If a word isn't mentioned in the doc entry for some function, it shouldn't have any magic way to affect that function.

The other thing I noticed with your questions: if you're curious what happens when you do X, just try it. If the kernel behaves in some inexplicable way, that's the point in time to investigate further. I imagine Stephen Wolfram sitting (or standing) in his office in MA; I bet it's in his muscle memory just to try something about before looking it up in the docs or (gasp!) asking another staffer for clarification.

POSTED BY: Phil Earnhardt
Posted 17 days ago

Is there any difference between Proficiency in Wolfram Language Level 1 Certification and Proficiency in Mathematica Level 1 Certification ? It seems that the requirements and the process are the same.

POSTED BY: Artur Piekosz

Good question! While there is significant overlap between the Wolfram Language and Mathematica Level 1 certifications, we are making changes to focus the Wolfram Language certification on programming, and the Mathematica certification on using the product for technical computation. The Level 1 pages and the exam questions will be reflecting these latest changes in upcoming days and weeks.

POSTED BY: Jamie Peterson

Hi there!

I have a question about adding a new variable (Key-> Value) to a list of associations. For instance I recreate the following data

{V1, V2} = {RandomVariate[NormalDistribution[15, 4], 50], 
RandomVariate[NormalDistribution[20, 7], 50]}; (*Create two random variables*)
data = AssociationThread[{"Diameter", "Height"} -> #] & /@  Thread[{V1, V2}];
(*Arrange a list of association*)

Suppose I want to add a new variable, for instance, the logarithm of Diameter variable, however, the only way I succed was using a implicit loop using the table function:

V3 = Log[data[[All, "Diameter"]]];
Table[Append[data[[i, All]], "LogDiameter" -> V3[[i]]], {i, 1, 
Length[V3]}];

I would like to ask if I could add a variable to the association list avoiding the Table function?

Thanks in advance!

Posted 17 days ago

Hi Andres,

Here is one way to do it

augmentedData = <|#, "LogDiameter" -> Log[#Diameter]|> & /@ data
Dataset@augmentedData

This relies on the implicit addition of key/value pairs to an Association when wrapped in Association. E.g.

assoc = <|"a" -> 1, "b" -> 2|>
<|assoc, "c" -> 3|>
(* <|"a" -> 1, "b" -> 2, "c" -> 3|> *)
POSTED BY: Rohit Namjoshi

Hi Andres—here are a few implementations that should get your thoughts moving,

If you have access to V1 and V2 directly, you can do:

new = AssociationThread[{"Diameter", "Height", "LogDiameter"} -> #] & /@ 
   Transpose[{V1, V2, V3}];

If you only have direct access to data, you could do this (honestly, I'd do something like this anyway):

new = <|"Diameter" -> #Diameter, "Height" -> #Height, 
     "LogDiameter" -> Log@#Diameter|> & /@ data;

The fastest and shortest way has got to be something like:

new = Append[#, "LogDiameter" -> Log@#Diameter] & /@ data;
POSTED BY: Arben Kalziqi

I just wanted everyone to know that the notebooks for the book "Query" are available at: Query notebooks. I have found them to be a helpful companion to our class.

POSTED BY: Michael O'Connor
Posted 18 days ago

When I click on the Grading Rubric link on this page I get

HTTP Error Code 403 Sorry, you do not have permission to access this item.

POSTED BY: Rohit Namjoshi

Hi Rohit, this should be fixed now—works for me, as well. You may need to clear cookies/cache to get it to work, though, as a version with the wrong permissions may be cached on your end.

POSTED BY: Arben Kalziqi

How to create the association command, "<|", vertical bar?

POSTED BY: Taiboo Song

It will depend on your keyboard layout, but a QWERTY layout should have the | accessible by pressing shift and . The < is just a less-than sign, so that's <|association here|>.

POSTED BY: Arben Kalziqi
Posted 18 days ago

Arben

The backslash needs to be escaped in the reply window. Shift \

Shift + \

POSTED BY: Rohit Namjoshi

oh god, it escapes even when there's nothing in front of it? blegh, thanks Rohit!

Taiboo: indeed, you want shift + backslash—shift + \

POSTED BY: Arben Kalziqi

Hello Arben: You are an excellent instructor and learning a lot.

When I open your filled-out notebook file, the file shows up as the notebook, with nice colors. But when I open the file class file, it looks different. Why is that and how to get into a nice notebook format for your class notes?

POSTED BY: Taiboo Song

Hey Taiboo—we have two versions of our notebooks, generally speaking. One is the instructor version, which I use when teaching live and which we use for making edits. Then, there's a more monochrome "handout" version which has some formatting changed for consistency's sake and to work nicely on the cloud.

POSTED BY: Arben Kalziqi
Posted 19 days ago

Arben - Two questions:

1.    On the Quiz, is there a way to find out which problem(s) we got wrong?

2.    My "Day01-ListsAndAssociations-Filled.nb" is filled with NULLs. Is there a way to resolve this?

Thanks in advance,

POSTED BY: Updating Name
  1. I don't think so, but if you have a question about a particular question you can ask me. (I also think that if you email us, we can manually pull your answers and which were correct.)
  2. No Nulls for me. You might get them if you don't Enable Dynamics when prompted.
POSTED BY: Arben Kalziqi

The quizzes used to indicate which ones were incorrect, but within the last year that was changed. I found the old method of indicating which answers were correct educational and the new method not so much.

Thanks,

Mitch Sandlin

POSTED BY: Mitchell Sandlin
Posted 19 days ago

I have some questions about the Manipulate construction: I have a manipulate with let's say 4 adjustable parameters.

  1. How can I make a button (Previous) to go to the previous values, without getting into an endless loop, which can easily happen in a Manipulate, as if one parameter is changed, everything is recalculated. I tried several ways, like putting the values in a nested list, but somehow there is always something that is not working. Ideally, I want to be able to step back several steps and also forward again (up to the last values I had). I hope my explanation is clear enough :-)

  2. How can I keep the last used values for the 4 parameters when I run the manipulate again? I believe that in a DynamicModule construction, that goes by itself.

  3. How can I easily save the values of the 4 params as a named Preset? Eg.: Preset1. I know that I can do 'Paste snapshot, which gives me all of the original code with the values of the moment, along with the result. This takes a lot of Notebook space, especially when the Manipulate code is substantial. I only want the values of the parameters, so I can load them back in later.

POSTED BY: B. Cornas

Great questions, B—any question I can't immediately answer must be pretty great ;). Let's see...

  1. I think I see what you mean, but some clarification wouldn't hurt. Could you provide a working example of a Manipulate and the behavior you'd like for it to exhibit? The thing about Manipulate is that—unless you specify otherwise via TrackedSymbols, Refresh, and similar—it will simply check for any symbol updates and it will re-compute the result. There's no way that's clear to me to get around this; the thing you're manipulating could depend arbitrarily on these inputs and other things, so it sort of needs to be that way. That said, sometimes you have a Manipulate where there's a "constant" piece which is expensive to compute, and the "dynamic" piece lives on top of it and is generally faster to compute. I don't think that that's what you're talking about, but if so, you can use With and Show to great effect for responsiveness—see attached.

  2. I have a kludgy solution for this and your third question. There's nothing stopping you from defining symbols within a Manipulate, so inside your manipulate you could say something like f[bValue=b,...] and then bValue would be Set to whatever the last value you used on your slider (or other interface element). You can use this as the starting point for the parameter too, so you'd simultaneously save all of your symbols and also be able to keep them as the starting point. Here's an example to get you going:

kValue = 1;
Manipulate[
 Plot[Sin[(kValue = k) x], {x, 0, 2 \[Pi]}], {{k, kValue}, .5, 3}]
Dynamic@kValue
POSTED BY: Arben Kalziqi
Posted 19 days ago

Somehow my post got posted under another name, so here I go again ;

Thanks Arben for your answers and for the truly excellent teaching you do. You bring something extra to the table, sometimes very subtle. Your teachings are top on all levels :-)

For the moment I reply to your answer to my questions 2+3.

I had also come up with creating secondary variables for the adjustable parameters in the Manipulate and assign the these params to the secondary variables. This way They are remembered outside the Manipulate loop. Also handy for debugging.

Building on your example, I came up with the following, which keeps the last used value when I run Manipulate again. (see code at end).

I can also make presets this way and via a Button load them back into Manipulate. I had hoped that there might be an easier way (a Wolfram function) that would do the job, as sometimes I have quite a lot of adjustable parameters in my Manipulates. But it is doable this way.

I'll post a Nb about my first question later.

Manipulate[ kValue = k; Plot[Sin[k x], {x, 0, 2 [Pi]}], {{k, kValue}, .5, 3, Appearance -> "Labeled"}]
POSTED BY: B. Cornas
Posted 18 days ago

Hi Arben, I've come up with an example Nb. It covers some of the 'Previous' and 'Next' possibilities, but not yet all. And it keeps the values last used.

Run the first cell before running the Manipulate, in order to provide initial values for the parameters inside Manipulate.

What it does is : 1. It keeps it's last values when running the Manipulate again, except for the Random pointsXY, which are newly generated each time the Manipulate is run.

  1. It steps back and forward (Button 'Previous' and 'Next'). This only works so far for the position of the lines (pointXY). Click 'Initialize X' and /or 'Initialize Y' buttons a couple of times and you can step back and forward. I limited the stepping back and forward , so no errors can occur (like asking for the a step before the first or beyond the last step).

Now I will try to be able to step back also for the other parameters, but something does not pan out yet.

Attachments:
POSTED BY: B. Cornas
Posted 19 days ago

TOPICS

It would be great if the following topics are covered, OR if there are other courses which cover them (I appreciate that some of these were touched on a bit):

custom packages , non-trivial function bodies, ordinary looping (includingPython-type looping), IDEs which work well, custom types (as in OO programming), name spaces, enums.

At least indicate what Wolfram language calls these structures, and where they are.

For example, list indexing was covered to excess, but there was only just brief touches of defining complicated functions. Custom packages are crucial for organizing any but the simplest programs, and ditto for IDEs. Sometimes speed is not important but flexibility in looping might be needed. Etc.

Thank you

POSTED BY: Steven Brawer

Thanks for the suggestions, Steven—we'll cover some of this in the coming days, and the full course offers a bit more insight than the slightly condensed study group. Once the full course is out later this month, please feel free to attend and tell us directly what you thought, if you'd like!

POSTED BY: Arben Kalziqi

Not in the file provided.

POSTED BY: Taiboo Song

Hi Taiboo, the amoeba folder where all of the materials live should have a data folder now which has all of the data used for today's presentation—as well as tomorrow's.

POSTED BY: Arben Kalziqi
Posted 20 days ago

The 2D slider

Manipulate[coordinate, {{coordinate, {0, 0},   "Coordinate"}, {-1, -1}, {1, 1}}] (* 2D slider *)

How would I do a 3D sider?

Manipulate[coordinate, {{coordinate, {0, 0,0},   "Coordinate"}, {-1, -1,-1}, {1, 1,1}}] (* 3D slider *) 

does not work

POSTED BY: Doug Beveridge
Posted 19 days ago

Doug, it would be great to have a 3D Slider. Unfortunately that is not possible on a 2D screen. How would you want to adjust the 3rd (z) axis on a 2D surface? I have been thinking more than 15 years about this and only have come up with complicated solutions, which are not truly 3D.

POSTED BY: B. Cornas
Posted 19 days ago

We Create 3D graphics on a 2D surface so we should be able to create a 3D slider .

I have noticed recently how graphics programs use a 3 button mouse to allow 3D movement in a 3D graphic , Is this not a possibility

POSTED BY: Doug Beveridge
Posted 19 days ago

We create 3D images on a 2D surface by means of perspective. To actually control 3 independent axes, you'll need 3 independent 'movements'. Of course, with extra buttons or scroll-wheels, you can add 3 third dimension, but never with a onscreen 3D slider.

What you could do, is assign the z direction to e.g. the y direction when ta button is pressed. But again, this would not be a real 3D slider, more of a work around.

POSTED BY: B. Cornas
Posted 19 days ago

Doug, it would be great to have a 3D Slider. Unfortunately that is not possible on a 2D screen. How would you want to adjust the 3rd (z) axis on a 2D surface? I have been thinking more than 15 years about this and only have come up with complicated solutions, which are not truly 3D.

If definitely possible on a 3D surface -- like what the Apple Vision Pro headset provides. That's why Apple is making such a big noise WRT the concept of "spatial computing". Check out the guided tour video published by Apple to get a taste of this. I suspect the hands-on demo -- now available at Apple stores -- would give a much better idea what this is all about. I fondly hope the Wolfram Research brain trust is checking out this tech and prototyping how they can use this tech for brilliant Spatial Computing visualizations.

On the 3D front, there is the work by Joan Horvath and Rich Cameron who have 3D printed objects designed to teach mathematical concepts: Make: Calculus, Make: Geometry, and Make: Trigonometry. AFAIK, nobody has tried to do create physical sliders in their 3DP objects; that's certainly doable. If you're really interested in 3D visualizations, I strongly suggest checking out these books and 3DP the objects that those books use.

POSTED BY: Phil Earnhardt

I also wanted to address Artur's question about @ vs. @* briefly.

It's true that in some contexts they are the same:

f@*g@x === f@g@x === f[g[x]]

but this isn't really the point of Composition/@*. The real use of this (in my experience) is chaining functions together for use in Map or Apply. Consider a basic example:

In[716]:= N@*Mean /@ {{1, 2, 4}, {4, 8, 9}}

Out[716]= {2.33333, 7.}

Here, the @* lets you write a "single composite object" which is the composition of N and Mean. This composition function is then what is mapped across the lists. Simply using @ doesn't do this:

In[715]:= N@Mean /@ {{1, 2, 4}, {4, 8, 9}}

Out[715]= {7/3, 7}

Why? What's happening—visible through Trace, which I'm going to check after I type this side note to confirm my Vibes (they were correct)—is that N@Mean gets evaluated first, and N acting on Mean just provides Mean because there's nothing there to make numeric.

So the idea is:

N@Mean /@ {{1, 2, 4}, {4, 8, 9}} = N[Mean] /@ {{1, 2, 4}, {4, 8, 9}} === Mean /@ {{1, 2, 4}, {4, 8, 9}} === {Mean@{1, 2, 4j}, Mean@{4, 8, 9}} 

whereas

N@*Mean /@ {{1, 2, 4}, {4, 8, 9}} === {N@*Mean@{1, 2, 4j}], N@Mean@{4, 8, 9}} === {N@Mean@{1, 2, 4j}], N@Mean@{4, 8, 9}} 

When composing functions, that's what you want. It can be really useful! Take the example from Good Coding Practices:

Framed@*Highlighted /@ {1, 2, 3} (* Unclear *)

(Framed@*Highlighted) /@ {1, 2, 3} (* Clearer *)

Map[Framed[Highlighted[#]] &, {1, 2, 3}] (* Clearest *)

You could rightfully argue that the first one is unclear, but if you understand how @* works it's very clear and very concise and very easy to write. You're taking the composed operation of "highlighting and then framing" and mapping it across the list {1,2,3}. It doesn't get better than that!

POSTED BY: Arben Kalziqi

The email announcing the recording availability didn't send me to the recording, just to the materials folder (no video there). Also, there was a link to the Quiz, which I'm hesitant to try without watching what went on today. Help?

POSTED BY: David Snyder
Posted 20 days ago

The e-mail announcing the availability of the recording of today's session was sent out at ~15:50 Eastern Standard Time today by the "Wolfram U Team". The subject is: "Recording available: Interfaces and Deployment". Search for "Wolfram U Team" in your inbox. The recording is accessed by clicking the "Watch The Recording" button in that e-mail. I called up the video; it is indeed today's recording.

--phil

POSTED BY: Phil Earnhardt
Posted 20 days ago

I did NOT receive this email.

POSTED BY: Steven Brawer

Please contact our staff at wolfram-u@wolfram.com if you need assistance with webinar email notifications from bigmarker.com. This is the mechanism that is used to send Daily Study Group reminders and recording notifications.

POSTED BY: Jamie Peterson
Posted 19 days ago

Jamie, it would be cool if Wolfram Research could maintain a list of those BigMarker video archive links for each user in a particular WSG and have them accessible through a Wolfram-U portal in the Wolfram Cloud. All of the user's information for that particular WSG would be stored there. That would provide a reliable mechanism for all users to have the URLs -- and not worry about losing an e-mail through spam filters, force majeure, or whatever. It would also function as a beautiful professional archive for students to reference those training materials in the future. It would be an engaging example for how users can set up small programs establishing highly accessible live data using the Wolfram Language for their own customers.

There's an expense setting this up, but a payout in reducing the day-to-day customer support and customer satisfaction.

I bet there are staffers who could implement this as a one-liner. ;)

POSTED BY: Phil Earnhardt

@Phil Earnhardt, I really like this idea! We have, in fact, had brainstorming sessions about building a Wolfram U portal that would help to archive links to past sessions and courses, certifications, and other useful information. It's good to be reminded there is interest out there. Thanks!

POSTED BY: Jamie Peterson
Posted 19 days ago

Well, good. The really interesting thing for me is having a cloud app that Wolfram U users would regularly be using -- and having some sense of what they could [cloud] deploy for themselves.

One of the amazing bits of code that Wolfram U has is the grading engine for the Elementary Introduction to the Wolfram Language course. Anyone who goes through that course without being amazed what the grading engine is doing is just not conscious! Like many, It's tricky: you must have answers that are being produced computationally, but the implementors could not have anticipated everything users could possibly do. I found myself tweaking my answers -- just to see what the engine would judge as "correct" or "incorrect". IMHO, the only shortcoming with the EIWL grading engine is that the source code is not available.

If/when you do this project, please design and implement it with the intention of making the Wolfram Language Notebook source publicly available. Students regularly using it should be curious about its implementation. And people will want to borrow/modify it for their own use; that's what you want. You may even want to do a BigMarker presentation where you walk through the source and explain what/why you do things (both for functionality and for code efficiency).

POSTED BY: Phil Earnhardt
Posted 19 days ago

Trying to understand what Trace is telling me here. I have your words but still do not quite follow. Is it possible to step through this?

Attachment

Attachments:
POSTED BY: Coe Miles

Sure—down the list:

  • The input (with explicit parentheses on the composite function)
  • The Map having been applied takes the composition function and "distributes" it to each term in the nested list, at top level (just f/@{a,b} === {f[a],f[b]})
  • The composite operation/function (N@*Mean) is acting on the first list {1,2,4}, which means that it should be applied like N[Mean[{1,2,4}]]. This is because a composite function f@*g—"the pure operator form of taking g of a thing and then taking f of the result"—acts such that f@*g on a means f[g[a]]. This is the definition of function composition, generally speaking. It's just that in Wolfram Language, we don't write f ∘ g, but f@*g.
  • The expression N[Mean[{1,2,4}]] is evaluated in standard order, from the inside out—first, the Mean is taken, giving 7/3, then N of that result is taken, giving 2.333...
  • The same series of operations is performed on the second list
  • The two results are provided with a List head/wrapper, as that's how Map works (cf. f/@(a+b) === f[a]+f[b] === Plus[f[a],f[b]])

Hopefully that helps, but let me know if not.

POSTED BY: Arben Kalziqi

Folks, it was indeed a trivial yet embarrassing issue—I still had expr defined as a + (b c)/d from last week's lecture :|. You can just do this, and it'll work:

integralAPI = APIFunction[
   {"func" -> "MathExpression"},
   "The integral of " <> ToString[#func] <> " is " <> 
     ToString@Integrate[#func, x] &
   ];

integralAPIDeployed = CloudPublish[
  integralAPI,
  "IntegralAPI"
  ]

As you can see in my deployed version here: https://www.wolframcloud.com/obj/online-courses/PracticalProgramming/IntegralAPI?func=sinx

POSTED BY: Arben Kalziqi

Hi Arben;

Last week you showed an example of Function[] used with a variable as well as a #. Was it your intention to compare a prime function and a non-prime function or a prime function using a # compared to another prime function using a name?

Thanks,

Mitch Sandlin

POSTED BY: Mitchell Sandlin

Hey Mitch—"pure" function! But the idea was primarily just to show the "spectrum" from a full, named function with named variables down to a function with no name and whose variables were unnamed. Function of any kind is technically a pure/anonymous function, even if you provide "dummy variable" names for the inputs just like you would in a definition like myNameFunc[x_]:=....

The progression I have in mind is:

mySineAdder[num_]:=num+Sin[num]
Function[num,num+Sin[num]]
Function[#+Sin[#]]
#+Sin[#]&

The first function is a named ("nonymous", you could say, had history taken a different turn). The last three are pure or "anonymous" functions.

POSTED BY: Arben Kalziqi
Posted 21 days ago

Hi Arben and all, I have a question about the last lesson about complexity time on function definition. I have done this notebook and I want to know if there is a simpler complexity way to code the problem.

PLEASE SEE THE NOTEBOOK ATTACHED TO THIS COMMENT

Thanks
Mauro

Attachments:
POSTED BY: Mauro Bertani

Hey Mauro—while I could probably figure this out if I sat and looked at it for a bit of time, I think I need to set the precedent that I can't take arbitrary code and rewrite it for you. However, what I am happy to do is to take an explanation of what your code is actually doing, with some examples, and tell you how I'd write a function that performs the operation in question.

POSTED BY: Arben Kalziqi
Posted 19 days ago

Ok, Arben. I think to have understood where I have made a mistake. It's very fuzzy, how speak with someone change our prospective, by only to expose the problem. Thanks Mauro

POSTED BY: Mauro Bertani

I understand—trying to figure out how to frame and phrase the problem to somebody else is often half the battle!

POSTED BY: Arben Kalziqi

Hey Arben,
In the Friday lecture you did a quick and dirty example of error trapping:

polygonMaker[n_Integer ] := Graphics[{Red, RegularPolygon[n]}]

Then you added a new statement in real time in your Notebook

polygonMaker[___] := "please enter a digit"

I thought basically the three dashes stand for "anything". But it seems in this context they stand for "anything else".
I don't understand the precedence here. How did "else" get implied? I would have thought it redefined the function polygonMaker to always say "please enter a digit" from now on, regardless of the argument. What happened here?

POSTED BY: Carl Hahn

I believe this is how it works: polygonMaker had two definitions entered into the database. When the function is called, the first version entered is called first, but if the type of the input type isn't an integer, then the next definition is called, which does have a response to anything else. The point is that the domain of polygonMaker was extended by adding that second step, but that extension is only checked when needed.(Technically it would be better for polygonMaker to catch integers less than three)

Here's another example to ponder (entered in successive cells).

f[x_Integer] := x*1.0  
f[x_Real] := IntegerPart[x]  
f[3]  
Out[187]= 3. 
f[3.0]. (* the first version can't be applied to 3.0 so the second version is called *)  
Out[188]= 3
POSTED BY: David Snyder

This is basically it—there are two definitions here, and if one doesn't fit it will try the other. Still, Carl's question of precedence is valid, because ___ really means anything given that it's "zero or more things". The answer is: precedence is given in order from most to least specific definitions.

POSTED BY: Arben Kalziqi

I had not picked up on that nuance even though I have used it (subconsciously?) as in the examples on recursion. I had not formally articulated in my head. WL does not pay attention to the sequence of definitions in code first, but yes to the hierarchy of precedence, which of course it does. Particular takes precedence over global. It's a grammar thing.

But if definitions have equal precedence, then it picks the most recent one. (Correct?)

POSTED BY: Carl Hahn

The documentation page linked by Rohit has this to say:

In the factorial function example used above, it is clear which rule is more general. Often, however, there is no definite ordering in generality of the rules you give. In such cases, the Wolfram System simply tries the rules in the order you give them.

You can check the order that definitions are stored—and tried—by evaluating ?func. (The fact that I had to check the documentation to be sure about this case should tell you something about its relative frequency, I hope!)

POSTED BY: Arben Kalziqi
Posted 20 days ago

For details on precedence / ordering see the documentation.

POSTED BY: Rohit Namjoshi
Posted 21 days ago

I wonder why the /@ stayed pupleRed in the last example of "Good Coding practices" (12. Pure Functions). See attached screenshot

Attachment

Attachments:
POSTED BY: B. Cornas

What I think happened is that he didn't put a space after the "/@" as he was doing it on the fly. It still ran on the fly. If you type it in yourself and put the space in there, it won't be red anymore. You might also see what happens to the # if you deleted the following &, it will turn red due to the syntax error.

POSTED BY: David Snyder
Posted 21 days ago

Thanks :-)

POSTED BY: B. Cornas

The spaces are really just a visual choice made by some programmers—I tend not to use them, and it shouldn't have this effect. I'll try to remember to check the full cell expression after today's class and see if I can figure out what's going on—if you look at the recording, you may note that I didn't expect that to look like that and am messing with it a little to investigate!

EDIT: Yeah, it's just written into the cell manually that that should have a particular background color. If you start typing into that space/editing it, you'll retain the color choice.

POSTED BY: Arben Kalziqi
Posted 4 days ago

Hi Arben, I do not understand what you mean by your last lines -after the EDIT:

I want to use different text colors for the comments in one cell. But of course still bracketet by (.........) to indicate that it is a comment. As some comments are temporarely (like (* FIX this later *) and other comments are permament, I would like different colors for the different kind of comments. As everything is adjustable in Mathematica, I would be surprised if this is not possible. Thanks, Bert

POSTED BY: B. Cornas

In that particular context, I meant that if you press (on mac) cmd + shift + e to see the full cell expression, you could see that the color was "baked in" there. I'd generally recommend only using this for clever little modifications, not as a "primary" means to do things (generally). But it can often provide some insight. As for coloring comments, I recommend just using the Style menu. (Maybe we already dismissed this for some reason, but if so I don't remember!)

POSTED BY: Arben Kalziqi

What I discovered on the MAC is that if you highlight just the text in the comment, not the (* *) at the beginning and the end of the comment, you can then go to the FORMAT drop down menu and select "Text Color". That will change only the color of the comment you are highlighting.

POSTED BY: Carl Hahn
Posted 21 days ago

I don't see an option to start a new Topic, so I just reply. I just saw Ahmed Elbanna's post, 4 days ago, and I agree :-)

Great webinars series. Arben is the absolute BEST presenter I have seen in all the webinars I have already watched. He does it just right on every level and in every detail. Arben, you're a fantastic teacher. You opened my eyes & understanding to new levels in things I already knew. I hope you'll be doing much more presentations.

My question : Is there a way to change the default color of a comment (* Comment *)? I can change the Size, Face, but not the color. This would be really convienient as to make an easy distinction between comments : * Explaining the code and function * Things that need repair, seriously * Things that need brushing up or speed enhancement * Alternative versions * Spots in the code that need extensions in the future * Etc.

It would really be great to have this color function. I know that I could do this with 'text' parts, but that will break the possibility to run the complete code with one Shift+ Enter.

POSTED BY: B. Cornas
Posted 21 days ago

Re. changing the default color of comments look at Preferences / Appearance

enter image description here

POSTED BY: Rohit Namjoshi
Posted 4 days ago

Hi Rohit, I just saw your answer to my first question a minute ago, while going through the list. I got a bit lost in the beginning. I actually now remember having found that it is possible to change the color for the comments. But what I am actually looking for is on the fly use different colors for different kind of comments. E,g. color 1 for code annotation Color 2 for alternatives Color 3 for comments like "Can be done better and faster" Etc.

POSTED BY: B. Cornas

Great course! (As usual from Wolfram). I really like the overall structure, the examples, the smaller checkpoints and the exercises at the end of each day.

Here are some improvements for the 5th exercise of Day 4

txt = ExampleData[{"Text", "DeclarationOfIndependence"}]
    (LetterCounts[txt, 2] // ReverseSort)[[;; 20]]

The solution provided uses Take[.., 20], this takes the first 20 elements. Not the 20 most frequent ones. Adding ReverseSort post fix style, sorts the association biggest->smallest. Similar with the second part.

((WordCounts[txt // DeleteStopwords] // ReverseSort))[[;; 20]]
POSTED BY: Fredrik Doberl

Let me know if I have this wrong, but I believe that LetterCounts is always automatically reverse-sorted by value and thus the first n elements—as taken by Take, for example—should always be the 20 most frequent elements. Do you have a counterexample in mind? (Or perhaps this behavior was different on an older version, perhaps pre-13 or even pre-12?)

EDIT: Oh, I see—there's an issue with the version where stopwords are deleted. Thanks for pointing that out; I'll fix it!

POSTED BY: Arben Kalziqi

Arben,

First thank you for teaching this class. This has been very helpful.

I am running into some unexpected behavior. I just downloaded Version 14, and when I do TreeForm of a list I get:

enter image description here

but when I do the same thing using Plus, I get:

enter image description here

I was expecting to get the same thing but with List replaced with Plus. I am a bit puzzled.

Many thanks for your help. Michael O'Connor

POSTED BY: Michael O'Connor

Hey Michael! The reason this happens is the order of evaluation. I have two suggestions for you to try which I think will clarify this behavior:

  1. Trace[TreeForm[Plus[1,2]]]

  2. TreeForm[List[a,b]] (=== TreeForm[{a,b}])

Let me know if this illuminates the difference for you.

POSTED BY: Arben Kalziqi

Also, Plus has the NumericFunction attribute whereas List does not. Thus one sees the following behavior from TreeForm:

enter image description here

POSTED BY: David Snyder

Arben, this does help! Thank you very much!!!

POSTED BY: Michael O'Connor
Posted 23 days ago

From yesterday's lesson, does anyone understand why

    larger[x_, y_] := If[x > y, x, y];
    Fold[larger, {3, 1, 2, 6, 5}]

returns larger[larger[larger[larger[3, 1], 2], 6], 5] and not 6?

POSTED BY: Coe Miles
Posted 23 days ago

I get 6 on my notebook.

POSTED BY: Steven Brawer

As do I. Coe, you might have given larger an incorrect definition that hasn't been overwritten for one reason or another—try restarting your kernel and running these two lines again? (Re: the new comment—the semicolon is fine. It's not necessary for SetDelayed definitions since the evaluation is, as claimed, delayed!)

POSTED BY: Arben Kalziqi
Posted 23 days ago

Try removing the semicolon

POSTED BY: Steven Brawer
Posted 24 days ago

map mystery

Can someone explain what is going on in the expressions below the tree, or would this be too advanced for the level of this course (which, if it is, is OK with me)?

(See attached png file)

Attachment

Attachments:
POSTED BY: Steven Brawer

Hey Steven—I think that these three points in concert are enough to answer your question, but please let me know if they don't:

  • Map[f,expr,n] maps f to expr down to level n
  • Map[f,expr,{n}] maps f to expr only at level n
  • Map[f,x] = x for AtomQ[x]==True (cf. our discussion yesterday: Map goes into the inside of an expression to work on its parts; atoms don't have parts so Map has nowhere to put the f—this could have been designed to produce an error message, but the decision was to have Map function such that if it can't map a function f somewhere, it just returns the object onto which f was asked to be mapped)
POSTED BY: Arben Kalziqi

Hey Arben,

Loving your class. Got a little exercise:

The transfer function of non linear power amplifiers produces inter-modulation products between the tones at their inputs. If the transfer function is expressed as a simple 5th order odd polynomial, and the input x is made of two sine waves at frequencies w1 and w2, you can easily find the mess that shows up at the output. It includes 3rd and 5th order inter-modulation products around the two tones, 3rd and 5th harmonics, and inter-modulation products around the harmonics. In RF systems we use band-pass filters to select only the fundamental tones and those tones around the fundamentals w1 and w2 (usually assumed to be closely spaced compared to the frequencies of the harmonics... Although audio systems will not be so cooperative.)

I've been playing around with some of the concepts I thought I was learning to take the output and literally select them, but it's not working yet. In the past I've just given up and brute forced it (yuk). This time round I'd like to learn how to do it right...help?

POSTED BY: Carl Hahn

We really do abhor a brute force solution. This is a fun little question; please see embedded response!

PLEASE SEE THE NOTEBOOK ATTACHED TO THIS COMMENT

Attachments:
POSTED BY: Arben Kalziqi

Thank you, Arben!!!

That's a really neat approach. Had not yet thought along the path of creating a list of all the terms. But entirely consistent with thinking about the heads and changing them. That's a powerful analytical tool.

Your solution has a lot of pedagogical value. I am going to be staring at it a bit.

If you are on a roll, I've got another one coming as soon as I can figure out how to ask it properly. Let me take a crack and if it needs more let me know: It has to do with a problem in FM theory, where recognizing that Cos (B Sin [w t]) can be expanded as a Fourier series whose coefficients are an ordinary Bessel Function of the first kind

= Jo(B) + 2 Sum (J2n(B) Cos (2 n w t) )

Then you have to truncate the series to get the coefficients of interest. There is a similar expansion for Sin(B Sin (w t). You can sample an FM signal and do an FFT and just see the spectrum, but recognizing the Bessel Function behavior provides an intuitive understanding of FM theory (bandwidth, mod index, S/N properties etc) that even when FM was really popular few people grasped. Now it's beginning to be a lost art. What I never figured out how to do was use WL pattern matching and mapping tools to "recognize" and derive this classical solution. It has other analytical advantages for other problems too.

POSTED BY: Carl Hahn

I really strive to provide pedagogically useful answers, so I appreciate it :). If I'm reading your (original) post correctly, you could also do pattern-matching or selection by going directly into the cosine terms, extracting the coefficients of the omegas with CoefficientList and grabbing only those cosine terms for which the absolute value of the difference is 1. This would make it so you don't even have to generate the desiredHarmonics list, if that's indeed what you want.

As for your new question, some more information would indeed be helpful. It's been a long time since I've dealt with this sort of thing, and certainly I've never approached it from the perspective of signal analysis and decomposition. But, fundamentally, you could write the same kind of thing as above with Cases, specifically recalling that Cases allows not just for pattern-matching but for term-rewriting too. So you could do something like:

Cases[expr,Cos[B___ Sin[ω t]]:>(full or truncated B-dependent sum here)]

This would extract all of the relevant cosine terms and rewrite them; you could update the rule to include both sine and cosine terms but I'm forgetting the way to do that right now. You could do something similar to the previous case and just extract all cosine or sine terms that have the right form, then use a simple /. to write a rule which appropriately converts the cosines and sines to their sum forms. You may also be interested in TruncateSum (new in 14), though this behavior was always manually implementable with a little elbow grease.

Otherwise, if you have an exact worked example, I'm pretty sure I could write something up reasonably quickly.

POSTED BY: Arben Kalziqi

Thanks Arben, I will get back to you on that FM question. I have to find my notes on when I last tried to do it.

"If I'm reading your (original) post correctly, you could also do pattern-matching or selection by going directly into the cosine terms, extracting the coefficients of the omegas with CoefficientList and grabbing only those cosine terms for which the absolute value of the difference is 1"

That sounds kinda like what I was originally trying to do but unsuccessfully. Could you show an example?

POSTED BY: Carl Hahn

Let's see:

PLEASE SEE THE NOTEBOOK ATTACHED TO THIS COMMENT

EDIT: Really better just to use Coefficient. I don't like CoefficientList anymore; it's dead to me. So this is probably the most efficiently and extensibly you could write it?

Cases[yexp, 
 c___*Cos[arg_] /; 
  Abs@Total@Coefficient[arg, {ω1, ω2}] == 1]
Attachments:
POSTED BY: Arben Kalziqi

Delicious!!! Once again a pedagogical Rosetta Stone. Thank you , Carl

POSTED BY: Carl Hahn
Posted 24 days ago

Hey everyone, care to take a stab at explaining why:

Total[{{a, b, c}, {u, v, w}, {x, y, z}}]

returns

{a + u + x, b + v + y, c + w + z}  (*One of our Day 4 "Check Your Understanding" questions*)

I've looked at the documentation for "Total" and still can't figure out how this result is obtained. Thanks in advance,

POSTED BY: Coe Miles

Hey Coe, I can explain this.

Total is documented to take the elements of a list and add them together. In other words:

Total[{a,b,c,...}] === Plus@@{a,b,c,...} === Plus[a,b,c,...]

In standard notation, that means that Total[{a,b,c,...}] just evaluates to a+b+c+.... Nothing too surprising here, I think.

The misunderstanding likely comes from two places.

Since Wolfram Language is fully symbolic by default, we never said what a, b, c and so on might be. They don't need to be reals or integers or even numbers—in fact, try this for me:

randomImages=Table[RandomImage[{0, 1}, {25, 25}], {2}]
Total@randomImages

If there is a sense in which the arguments inside the List fed to Total can be added, then Total will add them because it is very literally just performing the pattern-matching term-rewriting transformation rule I expressed above.

Now that we know what Total does, if we want to understand the output of Total[{{a, b, c}, {u, v, w}, {x, y, z}}], we need to ask: what does Plus do when fed multiple List objects?

You can try this out manually, but that's basically just rewriting the thing that we're not understanding in the first place. Instead, you might try Attributes[Plus]. You get back several attributes, but the important one here is Listable. If you check the documentation for that, you'll see examples which basically replicate the behavior that prompted this question:

In[1]:= {a, b, c} + {x, y, z}

Out[1]= {a + x, b + y, c + z}

This is to say: Listable functions automatically thread over their arguments when those arguments are lists. Most built-in mathematics functions are listable, and this attribute allows for highly optimized code compared to looping or even mapping.

In the case of Plus, this behavior also happens to correspond to the standard mathematical operation of addition acting on vectors, matrices, and tensors more generally. After all, if you have the vectors a, b, and c, you find their sum by element-wise addition, right? The same is true for matrices and so on. (And in fact, people are often lazy and will "add" a scalar to a vector when what they really mean is that they want to add a constant vector to a vector. For example, somebody might say x = <1,2,3>, then say something like x + 1, when really they mean x + <1,1,1>. This is also automatically handled by Listable; feel free to evaluate {a,b,c}+1 and see the result, or even {{a,b},{c,d}}+1.)

POSTED BY: Arben Kalziqi
Posted 24 days ago

Arben - Thank you very much for the detailed explanation. I am finding this material somewhat difficult but rich and rewarding when something sticks.

POSTED BY: Coe Miles
Posted 24 days ago

Tree walking - inconsistency or design

Given some algebraic expression y, I can do y[[3,2,5,1,..]] to walk the tree (or the full form) to a particular node.I can also do y[[0]] which is the same as y//Head. However, y[[0,2]], for example, is an error in my notebook, though presumably it should be the same as y[[2]].

This seems to me an inconsistency, but perhaps it is that way on purpose???? (In y[[3,2,5,1,..]], presumably the "0" is implicit.)

This is probably not a big deal, but I am bothered by stuff like this - a sort-of reflection edge condition that doesn't seem sensible.

POSTED BY: Steven Brawer

I don't think that this is an inconsistency: if you do extract a head with [[0]], that head does not have some internal structure that you can probe by asking to get its parts. What is the second part of Graphics?

POSTED BY: Arben Kalziqi
Posted 24 days ago

It seems to me the Head is just a node. I don't understand why it should be different from any other node. If it doesn't have a structure, why should any other node have a structure? I suppose there is something in the engine which interprets the head node differently from other nodes.

POSTED BY: Steven Brawer

I think I see what you mean; I think that that's fair enough if you're thinking about it in terms of TreeForm. The discrepancy, such as it is, exists because technically Part is always "reaching into" an expression (cf. the reason you can't [""] use Part on atoms is because they don't have an "inside" to reach into).

That is: whenever you say expr[[n]], you are going into expr and extracting something. If you have not just a single n, but exprp[[m,n,...]] then the number of elements in that sequence specifies the Depth at which you are accessing the structure of expr. The issue here is that expr[[0]] does indeed not work like this: because indexing in Wolfram Language starts at 1, this is not "getting a part" of expr in the same sense that expr[[n]] for n≥1 is, but is "special case", manually-implemented extra behavior.

I do see why one might consider this inconsistent, but my personal sense is that [[0]] is simply used as a convenient syntax shortcut for Head@. If we didn't have it, the behavior of Part would indeed be more consistent, but it would also be less functional for some particular uses... my perhaps-frustrating advice is to do a bit of compartmentalization about the meaning of Part, here. We're already doing that when using Part on SparseArray or Dataset atoms, so why not add one more case where Part is doing something which is maybe a little bit misleading...

Finally, I do want to clarify something: because this [[0]] is a special behavior which does not give you the 0th part in the technical sense (as there is no 0th part in a language which indexes from 1), it is not the case that there is an implicit 0 which starts off any Part sequence. Moreover, there's nothing in any given expr that you cannot access because of this: the entirety of the internal structure of expr (if it has any) is accessible without making any reference to any 0th part. It's just that if you would like to get not the internal structure, but the thing that wraps around that internal structure—which in the strict sense is not a part—then we allow you to do that with Part[expr,0] as a convenience.

The succinct version is maybe:

  • Part is really only intended to talk about the parts of a compound expression, and the "parts" of an expression are always internal to the expression.
  • Because you could already access everything about an expression but its head with Part, we added a special case of asking for """the zeroth part""" so that you could get that last bit of information without having to leave Part-world.
POSTED BY: Arben Kalziqi
Posted 24 days ago

Thanks. That's really helpful.

POSTED BY: Steven Brawer

In the "Check Your Understanding" exercise for pure functions we are told that Function[u, 3+#][x] is the correct syntax for returning 3+x given x as an argument.

I think that's incorrect (?)

POSTED BY: Paul Tikotin

Good catch! I've fixed this in our repo and it will be fixed in our next deployment.

POSTED BY: Arben Kalziqi
Posted 24 days ago

I asked in the BigMarker Q&A panel how to upload a WL Notebook to my Wolfram Cloud account. The reply was to use the "upload" button in the upper right corner of the Wolfram Cloud window. This doesn't work; I get the error message, "To access this feature, subscribe to a plan." Apparently, the Basic plan isn't good enough.

I can upload files through Mathematica on another machine through the File->Save to Cloud function. I don't understand why that works but simply doing an "upload" in cloud does not. Is there a good reason for keeping a random user from uploading any notebook to a Wolfram Cloud account through the web? If not, please file this as a bug.

One note for the staff answering questions: when they are answering a question like this, they should try to perform the function with the same level of privilege/access as a normal customer. In this case, the Wolfram Cloud "upload" function should have been tried on a Basic plan.

POSTED BY: Phil Earnhardt

Hi Phil,

I think this can be better understood and handled through contacting customer support:
https://www.wolfram.com/support/contact/email

POSTED BY: Ahmed Elbanna