While Loop in Power BI M script - while-loop

I'm trying to use a while loop in the M script. I'm very new to Power BI and the M syntax is quite confusing. I came to know that we need use list.generate() to loop through items.
How do we use list.generate in this scenario?
a=1
while a < 1000:
time.sleep(10)
response = requests.request("GET",url,headers=headers)
reportJsonResponse = json.dumps(response .json())
if reportJsonResponse.get('category') == 'ZZZ'
a+=1
else
a = 1000
How do we convert this script to M ?

Related

Power BI while loop

I'm trying to do a while loop in Power BI M language. But all of the logic are all over my head!
How would you translate a very simple loop like this into M language?
while X == True:
do abcdef
if Y == True:
end
Thanks very much!
Loops in M are probably best handled with the List.Generate function.
This article does a pretty good job at explaining how it works:
https://potyarkin.ml/posts/2017/loops-in-power-query-m-language/
Using this function, let's look at a more specific implementation of a while loop, say to find Fibonacci numbers less than 1000.
a = 1
b = 1
while b < 1000
b = a + b
a = b - a
would translate to M something like this:
let
data =
List.Generate(
() => [ a = 1, b = 1 ],
each [b] < 1000,
each [ b = [a] + [b], a = [b] ]
),
output = Table.FromRecords(data)[a]
in output
I'm not sure the best way to handle your break condition Y. It might depend on the specific problem.

What is faster to calculate: Large looped calculations or Vlookup on multiple large data grids?

This is a conceptual question that will help me before I start coding my next project. Which approach do you think will be faster?
Loop Calculations: An example of how it would be set up:
for i = 0 to 67
While x < 350
y = 0
While y < 600
Call solved() 'solves and returns "concentration"
If c(y, x) <> Empty = True Then
c(y, x) = c(row, x) + concentration
Else
c(y, x) = concentration
End If
y = y + 1
Wend
x = x + 1
Wend
Next i
Vlookup:
Using Matlab I can generate millions of solved data points and store them into a matrix. This can be stored in a database.
Restrictions: Only Access available as a database. and with the amount of data needed to be stored it will hit memory limit. Excel is not a good idea to store this much data as well.
Taking the restriction into account, I have thought of using multiple text files to store data and use Excel to search and pull values.
Theoretically, a search should be faster. But with different files to open up and a large matrix to look through, the speed will be affected. What do you guys think, and please input if there is a better approach. Thanks!

numpy.einsum for Julia? (2)

Coming from this question, I wonder if a more generalized einsum was possible. Let us assume, I had the problem
using PyCall
#pyimport numpy as np
a = rand(10,10,10)
b = rand(10,10)
c = rand(10,10,10)
Q = np.einsum("imk,ml,lkj->ij", a,b,c)
Or something similar, how were I to solve this problem without looping through the sums?
with best regards
Edit/Update: This is now a registered package, so you can Pkg.add("Einsum") and you should be good to go (see the example below to get started).
Original Answer: I just created some very preliminary code to do this. It follows exactly what Matt B. described in his comment. Hope it helps, let me know if there are problems with it.
https://github.com/ahwillia/Einsum.jl
This is how you would implement your example:
using Einsum
a = rand(10,10,10)
b = rand(10,10)
c = rand(10,10,10)
Q = zeros(10,10)
#einsum Q[i,j] = a[i,m,k]*b[m,l]*c[l,k,j]
Under the hood the macro builds the following series of nested for loops and inserts them into your code before compile time. (Note this is not the exact code inserted, it also checks to make sure the dimensions of the inputs agree, using macroexpand to see the full code):
for j = 1:size(Q,2)
for i = 1:size(Q,1)
s = 0
for l = 1:size(b,2)
for k = 1:size(a,3)
for m = 1:size(a,2)
s += a[i,m,k] * b[m,l] * c[l,k,j]
end
end
end
Q[i,j] = s
end
end

Matlab: how do I run the optimization (fmincon) repeately?

I am trying to follow the tutorial of using the optimization tool box in MATLAB. Specifically, I have a function
f = exp(x(1))*(4*x(1)^2+2*x(2)^2+4*x(1)*x(2)+2*x(2)+1)+b
subject to the constraint:
(x(1))^2+x(2)-1=0,
-x(1)*x(2)-10<=0.
and I want to minimize this function for a range of b=[0,20]. (That is, I want to minimize this function for b=0, b=1,b=2 ... and so on).
Below is the steps taken from the MATLAB's tutorial webpage(http://www.mathworks.com/help/optim/ug/nonlinear-equality-and-inequality-constraints.html), how should I change the code so that, the optimization will run for 20 times, and save the optimal values for each b?
Step 1: Write a file objfun.m.
function f = objfun(x)
f = exp(x(1))*(4*x(1)^2+2*x(2)^2+4*x(1)*x(2)+2*x(2)+1)+b;
Step 2: Write a file confuneq.m for the nonlinear constraints.
function [c, ceq] = confuneq(x)
% Nonlinear inequality constraints
c = -x(1)*x(2) - 10;
% Nonlinear equality constraints
ceq = x(1)^2 + x(2) - 1;
Step 3: Invoke constrained optimization routine.
x0 = [-1,1]; % Make a starting guess at the solution
options = optimoptions(#fmincon,'Algorithm','sqp');
[x,fval] = fmincon(#objfun,x0,[],[],[],[],[],[],...
#confuneq,options);
After 21 function evaluations, the solution produced is
x, fval
x =
-0.7529 0.4332
fval =
1.5093
Update:
I tried your answer, but I am encountering problem with your step 2. Bascially, I just fill the my step 2 to your step 2 (below the comment "optimization just like before").
%initialize list of targets
b = 0:1:20;
%preallocate/initialize result vectors using zeros (increases speed)
opt_x = zeros(length(b));
opt_fval = zeros(length(b));
>> for idx = 1, length(b)
objfun = #(x)objfun_builder(x,b)
%optimization just like before
x0 = [-1,1]; % Make a starting guess at the solution
options = optimoptions(#fmincon,'Algorithm','sqp');
[x,fval] = fmincon(#objfun,x0,[],[],[],[],[],[],...
#confuneq,options);
%end the stuff I fill in
opt_x(idx) = x
opt_fval(idx) = fval
end
However, it gave me the output is:
Error: "objfun" was previously used as a variable, conflicting
with its use here as the name of a function or command.
See "How MATLAB Recognizes Command Syntax" in the MATLAB
documentation for details.
There are two things you need to change about your code:
Creation of the objective function.
Multiple optimizations using a loop.
1st Step
For more flexibility with regard to b, you need to set up another function that returns a handle to the desired objective function, e.g.
function h = objfun_builder(x, b)
h = #(x)(objfun(x));
function f = objfun(x)
f = exp(x(1))*(4*x(1)^2+2*x(2)^2+4*x(1)*x(2)+2*x(2)+1) + b;
end
end
A more elegant and shorter approach are anonymous functions, e.g.
objfun_builder = #(x,b)(exp(x(1))*(4*x(1)^2+2*x(2)^2+4*x(1)*x(2)+2*x(2)+1) + b);
After all, this works out to be the same as above. It might be less intuitive for a Matlab-beginner, though.
2nd Step
Instead of placing an .m-file objfun.m in your path, you will need to call
objfun = #(x)(objfun_builder(x,myB));
to create an objective function in your workspace. In order to loop over the interval b=[0,20], use the following loop
%initialize list of targets
b = 0:1:20;
%preallocate/initialize result vectors using zeros (increases speed)
opt_x = zeros(length(b))
opt_fval = zeros(length(b))
%start optimization of list of targets (`b`s)
for idx = 1, length(b)
objfun = #(x)objfun_builder(x,b)
%optimization just like before
opt_x(idx) = x
opt_fval(idx) = fval
end

Matlab: Optimize this?

Im v new to matlab. Have been tasked with speeding up a procedure. Im sure there is a better way to do the following statements:
for i = 2:length(WallId)
if WallId(i) ~= WallId(i-1)
ReducedWallId = [ReducedWallId;WallId(i)];
ReducedWallTime = [ReducedWallTime;WallTime(i)];
GroupCount = [GroupCount;tempCount];
tempCount = 1;
else
tempCount = tempCount +1;
end
end
I can preallocate the various vars to 'length(WallId)' but what do I do with the extra after its done? Do I care?
idx = find([true diff(WallId) ~= 0]);
ReducedWallId = WallId(idx);
ReducedWallTime = WallTime(idx);
GroupCount = diff([idx numel(WallId)+1]);
Assuming what you want is a summary of the unique data in WallId and WallTime, then you should
make sure that WallId is sorted first. You can re-organise WallTime to match, as follows:
[WallId, ind] = sort(WallId);
WallTime = WallTime(ind);
Also, you'll only get the right answer if WallTime matches whenever WallId does.
Use vectorization.
ReducedWallId=WallId(find(diff(WallId)~=0));
and similarly for ReducedWallTime.
The explicit for-loops are extremely slow. Using vector-operations speeds everything up considerably. This is a general theme in optimizing MATLAB code and is covered in detail in various documents found in the web.