nested if conditionalConstruct in Mathematica - wolfram-mathematica

Do you know If and how can I rewrite the code below in a better form for different values of m,k,l?
It is a nested if loop that I want to to check b for all m,k,l, but the code below is too big, I would like to simplify it. Can I?
If[b > m, If[(b - 1) > k, If[(b - 2) > l, b - 3, b - 2],
If[(b - 1) > l, b - 2, b - 1]], If[b < m,
If[(b + 1) > k, If[(b + 2) < l, b + 3, b + 2], If[(b + 1) < l, b + 2, b + 1]],
If[b > k, If[(b - 1) > l, b - 2, b - 1], If[b < k, If[(b + 1) < l, b + 2, b + 1],
If[b > l, b - 1, If[b < l, b + 1, b]]]]]]
Thanks!

Notice that you have If statements for both b > m and b < m, as well as b > k and b < k. These pairs can each be two halves of the one If statement.
Convert all the top level conditionals into a Which statement. Look up the documentation in Mathematica for more information.
You can probably also convert the relationships between b and l to simpler Which statements.

Related

ascending order check recursively

What I try to do is to check a given array is ordered in an ascending manner by divide-and-conquer approach.
I wonder what the logic behind the additional return case (a⌊n/2⌋−1 ≤ a⌊n/2⌋) is to reach to the final result. I attempted to solve the problem without looking at its solution but I couldn't figure out how the author discovers/devises a⌊n/2⌋−1 ≤ a⌊n/2⌋ case. It is really hard for me to unearth the case.
Actually, Why not a⌊n/2⌋ ≤ a⌊n/2⌋+1 instead? And the base case case, why I'm stackoverflowed when I remove equality from the base case, that is h<l?
with trial and error approach, I tried to write the following.
def co(a, l, h):
if h <= l:
return True
mid = l + ((h-l)//2)
cl = co(a, l, mid-1)
rl = co(a, mid+1, h)
return rl and cl and a[mid] < a[mid+1]
# how is a[mid] < a[mid+1] devised ??
# why not a[mid-1] < a[mid] ??
#c = [3, 5, 7, 9, 11,12]
c = [3, 5]
print(co(c, 0, len(c) - 1))
And the base case case, why I'm stackoverflowed when I remove equality
from the base case, that is h<l?
Assume c=[3, 5]. If you replace h<=l with h<l, then when you compute co(a, 1, 1), then mid = 1+0 ... then rl = co (a, 1+1, 1) and a[2] gives you stackoverflow.
How is a[mid] <= a[mid+1] devised ??
You need to compare the most-right element of subproblem1 with the most-left element of subproblem2. The order of these two elements are not taken into account in subproblem1 and subproblem2.
Be careful with Python indexing. 1) When you split the list into a[l:mid-1] and a[mid+1,h], you leave out a[mid-1] and a[mid]. 2) When you write co(c, 0, len(c) - 1) you leave out the last element of c (see Comment4).
There are some mistakes in your code, see my comments.
def co(a, l, h):
if h <= l:
return True
mid = l + ((h-l)//2)
cl = co(a, l, mid-1)
rl = co(a, mid+1, h)
return rl and cl and a[mid] < a[mid+1] ### Comment1: this misses checking a[mid-1] <= a[mid]
# how is a[mid] < a[mid+1] devised ?? ### Comment2: you should use <= rather than <
# why not a[mid-1] < a[mid] ??
#c = [12, 3, 5, 7, 9, 11,12] ### Comment3: your code returns True for this unordered list!
#c = [3, 5, 7, 9, 11,12]
c = [3, 5]
print(co(c, 0, len(c) - 1)) ### Comment4: len(c)-1 should be len(c) otherwise it's not the whole list
Below, I fixed the list indexing in your code. Note that the test becomes h <= l+1 because in Python the list a[mid:mid+1] contains one element.
def co(a, l, h):
if h <= l+1:
return True
mid = l + ((h-l)//2)
cl = co(a, l, mid)
rl = co(a, mid, h)
return rl and cl and a[mid-1] <= a[mid]

Recursive Maximum Subsequence Sum With No Three Consective Elements

I am attempting to solve, using recursion a way to maximize sub sequence sum such that no three elements are consecutive.
There is a way to do this by dynamic programming but I want to build on it using recursion first.
Some sample input and outputs:
Input:{1, 2, 3}
Output: 5
Input:{100, 1000, 100, 1000, 1}
Output: 2101
Input:{1, 2, 3, 4, 5, 6, 7, 8}
Output: 27
I am able to get mostly correct results apart from the second one {100, 1000, 100, 1000, 1}.
My solution:
int maxSubsequenceSum(vector<int> nums)
{
return helper(nums, nums.size());
}
int helper(vector<int>& nums, int index)
{
if (index <= 0) return 0;
int withoutThird = helper(nums, index - 3) + nums[index - 1] + nums[index - 2];
int withoutSecond = helper(nums, index - 3) + (index - 1 < 0 ? 0 : nums[index - 1]) + (index - 3 < 0 ? 0 : nums[index - 3]);
int withoutFirst = helper(nums, index - 3) + (index - 2 < 0 ? 0 : nums[index - 2]) + (index - 3 < 0 ? 0 : nums[index - 3]);
return max(withoutThird, max(withoutSecond, withoutFirst));
}
Individually the three withoutThird, withoutSecond and withoutFirst give the correct result only whilst in a recursive arrangement it fails. Why does it fail and is this a correct recursive approach?
The problem is to get maximum with no three consecutive elements.
What you are doing is, taking 3 elements at a time, select two having maximum sum from it, add them and so on.
Taking one example :-
Input : {A, B, C, D, E, F}
As your recursion goes right to left.
Assume, taking, {D, E, F}
(D + E) > (E + F) and (D + E) > (D + F)
Your code will select {D, E} from last 3 elements.
Now, taking, {A, B, C} Assuming,
(B + C) > (A + B) and (B + C) > (A + C)
Your code will select {B, C} from first 3 elements.
Total Selected Elements = {B, C, D, E}.
Noticed Something?
You ended up adding four continuous elements.
One short example : {100, 1000, 100, 1000, 1}
2 windows : [0,1] and [2,4]
Selected {100, 1000} from [2, 4]
and Selected {100, 1000} from [0, 1]
Added up four continuos elements.
Got: 2200, which is your actual output.
Hint: Try to pass the element index which u didn't add from one state of recursion to another. If still stuck, comment and I will write a similar code :)
Problem
withoutSecond and withoutFirst has some bugs. To make it simpler, let's assume index >= 3. Look at withoutSecond:
withoutSecond = helper(nums, index - 3) + nums[index - 1] + nums[index - 3]
It picks index-1 and index-3. So if we pick index-4 in helper(nums, index - 3) then we can not pick index-5, but it contains in withoutThird in function helper(nums, index - 3). That would yield a larger result than expected.
Algorithm
As the condition is does not allow 3 consecutive elements. So we only need to consider 2 consecutive elements to decide if we should pick another or not.
Suppose f(a, n) calculates largest result of array a with size n.
If does not pick a[n]: f(a, n) -> f(a, n-1)
If pick a[n] && pick a[n-1]: f(a, n) -> f(a, n-3) + a[n] + a[n-1]
If pick a[n] && not pick a[n-1]: f(a, n) -> f(a, n-2) + a[n]
OK, that's all the 3 cases.
Code
See the following code for details
#include <vector>
#include <cstdio>
using namespace std;
// this runs slow
// but you can use memorized search to speed up the process
int helper(vector<int>& nums, int index) {
if (index == 0) return 0;
if (index == 1) return nums[0];
if (index == 2) return nums[0] + nums[1];
int without_last_1 = helper(nums, index-1);
int with_last_1_and_2 = helper(nums, index-3) + nums[index-1] + nums[index-2];
int with_last_1_and_without_last_2 = helper(nums, index-2) + nums[index-1];
return max(without_last_1, max(with_last_1_and_2, with_last_1_and_without_last_2));
}
int maxSubsequenceSum(vector<int> nums) {
return helper(nums, nums.size());
}
int main() {
printf("%d\n", maxSubsequenceSum({1, 2, 3}));
printf("%d\n", maxSubsequenceSum({100, 1000, 100, 1000, 1}));
printf("%d\n", maxSubsequenceSum({1, 2, 3, 4, 5, 6, 7, 8}));
return 0;
}

Error in RecurrenceTable with symbolic input

I am finally working on my n-point Pade code, again, and I am running across an error that was not occurring previously. The heart of the matter revolves around this code:
zi = {0.1, 0.2, 0.3}
ai = {0.904837, 1.05171, -0.499584}
Quiet[ RecurrenceTable[ {A[0] == 0, A[1] == ai[[1]],
A[n+1]==A[n] + (z - zi[[n]]) ai[[n+1]] A[n-1]},
A, {n, Length#ai -1 } ],
{Part::pspec}]
(The use of Quiet is necessary as Part complains about zi[[n]] and ai[[n+1]] when n is purely symbolic.) The code itself is part of a function that I want a symbolic result from, hence z is a Symbol. But, when I run the above code I get the error:
RecurrenceTable::nlnum1:
The function value {0.904837,0.904837+0. z} is not a list of numbers with
dimensions {2} when the arguments are {0,0.,0.904837}.
Note the term {0.904837,0.904837+0. z} where 0. z is not reduced to zero. What do I need to do to force it to evaluate to zero, as it seems to be the source of the problem? Are there alternatives?
Additionally, as a general complaint about the help system for the Wolfram Research personnel who haunt stackoverflow: in v.7 RecurrenceTable::nlnum1 is not searchable! Nor, does the >> link at the end of the error take you to the error definition, but takes you to the definition of RecurrenceTable, instead, where the common errors are not cross-referenced.
Edit: After reviewing my code, the solution I came up with was to evaluate the RecurrenceTable completely symbolically, including the initial conditions. The working code is as follows:
Clear[NPointPade, NPointPadeFcn]
NPointPade[pts : {{_, _} ..}] := NPointPade ## Transpose[pts]
NPointPade[zi_List, fi_List] /; Length[zi] == Length[fi] :=
Module[{ap, fcn, rec},
ap = {fi[[1]]};
fcn = Module[{gp = #, zp, res},
zp = zi[[-Length#gp ;;]];
res = (gp[[1]] - #)/((#2 - zp[[1]]) #) &[Rest#gp, Rest#zp];
AppendTo[ap, res[[1]]];
res
] &;
NestWhile[fcn, fi, (Length[#] > 1 &)];
(*
The recurrence relation is used twice, with different initial conditions, so
pre-evaluate it to pass along to NPointPadeFcn
*)
rec[aif_, zif_, a_, b_][z_] :=
Evaluate[RecurrenceTable[
{A[n + 1] == A[n] + (z - zif[n])*aif[n + 1]*A[n - 1],
A[0] == a, A[1] == b},
A, {n, {Length#ap - 1}}][[1]]];
NPointPadeFcn[{zi, ap, rec }]
]
NPointPadeFcn[{zi_List, ai_List, rec_}][z_] /; Length[zi] == Length[ai] :=
Module[{aif, zif},
zif[n_Integer] /; 1 <= n <= Length[zi] := zi[[n]];
aif[n_Integer] /; 1 <= n <= Length[zi] := ai[[n]];
rec[aif, zif, 0, ai[[1]]][z]/rec[aif, zif, 1, 1][z]
]
Format[NPointPadeFcn[x_List]] := NPointPadeFcn[Shallow[x, 1]];
Like the built-in interpolation functions, NPointPade does some pre-processing, and returns a function that can be evaluated, NPointPadeFcn. The pre-processing done by NPointPade generates the list of ais from the zis and the function values at those points, in addition to pre-evaluating the recurrence relations. When NPointPadeFcn is supplied with a z value, it evaluates two linear recurrence relations by supplying it with the appropriate values.
Edit: for the curious, here's NPointPade in operation
In the first plot, it is difficult to tell the difference between the two functions, but the second plot shows the absolute (blue) and relative (red) errors. As written, it takes a very long time to create a Pade for 20 points, so I need to work on speeding it up. But, for now, it works.
You can hide part extraction behind a function:
In[122]:= zi = {0.1, 0.2, 0.3};
ai = {0.904837, 1.05171, -0.499584};
In[124]:= zif[n_Integer] /; 1 <= n <= Length[zi] := zi[[n]]
aif[n_Integer] /; 1 <= n <= Length[ai] := ai[[n]]
In[127]:= RecurrenceTable[{A[0] == 0, A[1] == aif[1],
A[n + 1] ==
A[n] + (z - zif[n]) aif[n + 1] A[n - 1]}, A, {n, (Length#ai) - 1}]
Out[127]= {0.904837, 0.904837,
0.904837 - 0.271451 aif[4] + 0.904837 z aif[4]}
EDIT
Here is the work-around for the problem:
In[4]:= zi = {0.1, 0.2, 0.3};
ai = {0.904837, 1.05171, -0.499584};
In[6]:= zif[n_Integer] /; 1 <= n <= Length[zi] := zi[[n]]
aif[n_Integer] /; 1 <= n <= Length[ai] := ai[[n]]
In[8]:= Block[{aif, zif},
RecurrenceTable[{A[0] == 0, A[1] == aif[1],
A[n + 1] == A[n] + (z - zif[n]) aif[n + 1] A[n - 1]},
A, {n, 0, (Length#ai) - 1}]]
Out[8]= {0, 0.904837, 0.904837}
Block serves to temporarily remove definitions of aif and zif while RecurrenceTable is executed. Then, when Block exits, the values are restored, and the output of RecurrenceTable evaluates.
It seems to me that Sasha's approach can be mimicked by just Blocking Part.
zi = {0.1, 0.2, 0.3};
ai = {0.904837, 1.05171, -0.499584};
Block[{Part},
RecurrenceTable[{A[0] == 0, A[1] == ai[[1]],
A[n + 1] == A[n] + (z - zi[[n]]) ai[[n + 1]] A[n - 1]},
A, {n, Length#ai - 1}]
]
{0, 0.904837, 0.904837}
Addressing Sasha's criticism, here are two other ways one might approach this:
With[{Part = $z},
RecurrenceTable[{A[0] == 0, A[1] == ai[[1]],
A[n + 1] == A[n] + (z - zi[[n]]) ai[[n + 1]] A[n - 1]},
A, {n, Length#ai - 1}]
] /. $z -> Part
-
With[{Part = Hold[Part]},
RecurrenceTable[{A[0] == 0, A[1] == ai[[1]],
A[n + 1] == A[n] + (z - zi[[n]]) ai[[n + 1]] A[n - 1]},
A, {n, Length#ai - 1}]
] // ReleaseHold

How to solve recursion relations analytically in mathematica?

For example, I have the following recursion and I want to get f[3,n]:
f[m_, n_] := Module[{}, If[m < 0, Return[0];];
If[m == 0, Return[1];];
If[2*m - 1 >= n, Return[0];];
If[2*m == n, Return[2];];
If[m == 1, Return[n];];
Return[f[m, n - 1] + f[m - 1, n - 2]];]
f[3, n]
The code does not seem to work. Please help. Many thanks!
You have an infinite recursion because when m is not initialized, none of the boundary cases match.
Instead of using Return you'll get more predictable behavior if you use functional programming, ie
f[m_, n_] := Which[
m < 0, 0,
2 m - 1 >= n, 0,
2 m == n, 2,
m == 1, n,
True, f[m, n - 1] + f[m - 1, n - 2]
]
In this case Which can not decide which option to take with n not initialized, so f[3, n] will return an expression.
One way to get a formula is with RSolve. Doesn't look like it can solve this equation in full generality, but you can try it with one variable fixed using something like this
Block[{m = 3},
RSolve[f[m, n] == f[m, n - 1] + f[m - 1, n - 2], f[m, n], {n}]
]
In the result you will see K[1] which is an arbitrary iteration variable and C[1] which is a free constant. It's there because boundary case is not specified

How to compute recursion relations in mathematica efficiently?

I have a recursion to solve for.
f(m,n)=Sum[f[m - 1, n - 1 - i] + f[m - 3, n - 5 - i], {i, 2, n - 2*m + 2}] + f[m - 1, n - 3] + f[m - 3, n - 7]
f(0,n)=1, f(1,n)=n
However, the following mma code is very inefficient
f[m_, n_] := Module[{},
If[m < 0, Return[0];];
If[m == 0, Return[1];];
If[m == 1, Return[n];];
Return[Sum[f[m - 1, n - 1 - i] + f[m - 3, n - 5 - i], {i, 2, n - 2*m + 2}] + f[m - 1, n - 3] + f[m - 3, n - 7]];]
It takes unbearably long to compute f[40,20]. Could anyone please suggest an efficient way of doing this? Many thanks!
Standard trick is to save intermediate values. The following takes 0.000025 seconds
f[m_, n_] := 0 /; m < 0;
f[0, n_] := 1;
f[1, n_] := n;
f[m_, n_] := (f[m, n] =
Sum[f[m - 1, n - 1 - i] + f[m - 3, n - 5 - i], {i, 2,
n - 2*m + 2}] + f[m - 1, n - 3] + f[m - 3, n - 7]);
AbsoluteTiming[f[40, 20]]

Resources