Guessing asymptotic upper bound by recursion tree. Verifying by substutution method and by Master Theorem - recurrence

My assignment is as follows:
Find a guress for an asymptotic upper bound for the recurrence by using recursion trees. Verify the asymptotic upper bound by:
1: Substitution method
2: Master Theorem
T(n)= { Θ(1) if n = 1
{ 3T(n/3) + Θ(n) if n > 1
how do i approach this?
I have some knowledge of recurrence trees, the substitution method and the Master Theorem. Please Help!

We have Case 2 of the Master theorem because
a = 3
b = 3
f(n) = n = Θ(n^log_3(3)) = Θ(n)
Therefore
T(n) = Θ(n*lg(n))
Of course
lg(n) = log_2(n).
Intuitively this means the cost of T is dominated neither by the cost of recursion nor by the work done in the recursion. This is the same as saying that in the recursion tree, the cost of the nodes at each level is asymptotically the same as the cost of leaves.
http://web.eecs.utk.edu/~parker/Courses/CS581-spring14/Lectures/3-Jan-16-Master-Mthd-Matrix-Mult-no-answers.pdf

Related

Genetic Algorithm timeseries forcast creating an initial population

I am building a genetic algorithm that does a time series forecast in the symbolic regression analysis. I’m trying to get the algorithm to find an equation that will match the underlying trend of the data. (predict monthly beer sales)
The idea is to use lisp like expressions, which writes the equation in a tree. This allows for branch swapping in the crossover/mating stage.
5* (5 +5)
Written as:
X = '(mul 5 (add 5 5))'
Y = parser(X)
y = ['mul', 5, ['add', 5, 5]]
I want to know how to create an initial population set where the individuals represent different expressions automatically. Where there “fitness” is related to how well each equation matches the underlying trend.
For example, one individual could be: '(add 100 (mul x (sin (mul x 3))))'
Where x is time in months.
How do I automatically generate expressions for my population? I have no idea how to do this, any help would be very appreciated.
You can easily solve this problem with recursion and a random number generator random() which returns a (pseudo-)random float between 0 and 1. Here is some pseudocode:
randomExp() {
// Choose a function(like mul or add):
func = getRandomFunction() // Just choose one of your functions randomly.
arg1 = ""
rand1 = random()
// Choose the arguments. You may choose other percentages here depending how deep you want it to be and how many 'x' you want to have.
if(rand1 < 0.2)
arg1 = randomExp() // Here add a new expression
else if(rand1 < 0.5)
arg1 = "x"
else
arg1 = randomConstant() // Get a random constant in a predefined range.
// Do the same for the second argument:
arg2 = ""
…
…
// Put everything together and return it:
return "("+func+" "+arg1+" "+arg2+")"
}
You might want to also limit the recursion depth, as this might return you a theoretically infinitely long expression.

Longest path in a graph

Given a undirected graph with vertices form 0 to n-1, write a function that will find the longest path (by number of edges) which vertices make an increasing sequence.
What kind of approach would you recommend for solving this puzzle?
You can transform the original graph into a Directed Acyclic Graph by replacing each of the (undirected) edges by a directed edge going towards the node with bigger number.
Then you end up with this: https://www.geeksforgeeks.org/find-longest-path-directed-acyclic-graph/
I would do a Dynamic Programming algorithm. Denote L(u) to be the longest valid path starting at node u. Your base case is L(n-1) = [n-1] (i.e., the path containing only node n-1). Then, for all nodes s from n-2 to 0, perform a BFS starting at s in which you only allow traversing edges (u,v) such that v > u. Once you hit a node for which you've already started at (i.e., a node u such that you've already computed L(u)), L(s) = longest path from s to u + L(u) out of all possible u > s.
The answer to your problem is the node u that has the maximum value of L(u), and this algorithm is O(E), where E is the number of edges in your graph. I don't think you can do faster than this asymptotically
EDIT: Actually, the "BFS" isn't even a BFS: it's simply traversing the edges (s,v) such that v > s (because you have already visited all nodes v > s, so there's no traversal: you'll immediately hit a node you've already started at)
So actually, the simplified algorithm would be this:
longest_path_increasing_nodes():
L = Hash Map whose keys are nodes and values are paths (list of nodes)
L[n-1] = [n-1] # base case
longest_path = L[n-1]
for s from n-2 to 0: # recursive case
L[s] = [s]
for each edge (s,v):
if v > s and length([s] + L[v]) > length(L[s]):
L[s] = [s] + L[v]
if length(L[s]) > length(longest_path):
longest_path = L[s]
return longest_path
EDIT 2022-03-01: Fixed typo in the last if-statement; thanks user650654!
There are algorithms like Dijkastras algorithm which can be modified to find the longest instead of the shortest path.
Here is a simple approach:
Use a recursive algorithm to find all paths between 2 nodes.
Select the longest path.
If you need help with the recursive algorithm just ask.

Recurrence Relation tree method

I am currently having issues with figuring our some recurrence stuff and since I have midterms about it coming up soon I could really use some help and maybe an explanation on how it works.
So I basically have pseudocode for solving the Tower of Hanoi
TOWER_OF_HANOI ( n, FirstRod, SecondRod, ThirdRod)
if n == 1
move disk from FirstRod to ThirdRod
else
TOWER_OF_HANOI(n-1, FirstRod, ThirdRod, SecondRod)
move disk from FirstRod to ThirdRod
TOWER_OF_HANOI(n-1, SecondRod, FirstRod, ThirdRod)
And provided I understand how to write the relation (which, honestly I'm not sure I do...) it should be T(n) = 2T(n-1)+Ɵ(n), right? I sort of understand how to make a tree with fractional subproblems, but even then I don't fully understand the process that would give you the end solution of Ɵ(n) or Ɵ(n log n) or whatnot.
Thanks for any help, it would be greatly appreciated.
Assume the time complexity is T(n), it is supposed to be: T(n) = T(n-1) + T(n-1) + 1 = 2T(n-1) + 1. Why "+1" but not "+n"? Since "move disk from FirstRod to ThirdRod" costs you only one move.
For T(n) = 2T(n-1) + 1, its recursion tree will exactly look like this:
https://www.quora.com/What-is-the-complexity-of-T-n-2T-n-1-+-C (You might find it helpful, the image is neat.) C is a constant; it means the cost per operation. In the case of Tower of Hanoi, C = 1.
Calculate the sum of the cost each level, you will easily find out in this case, the total cost will be 2^n-1, which is exponential(expensive). Therefore, the answer of this recursion equation is Ɵ(2^n).

Determine upper/lower bound for variables in an arbitrary propositional formula [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
Given an arbitrary propositional formula PHI (linear constraints on some variables), what is the best way to determine the (approximate) upper and lower bound for each variable?
Some variables may be unbounded. In this case, an algorithm should conclude that there's no upper/lower bound for those variables.
e.g., PHI = (x=3 AND y>=1). The upper and lower bound for x are both 3. The lower bound for y is 1, and y does not have an upper bound.
This is a very simple example, but is there a solution in general (perhaps using SMT solver)?
This assumes the SAT/UNSAT domain of each variable is continuous.
Use an SMT solver to check for a solution to the formula. If there's no solution then that means no upper/lower bounds, so stop.
For each variable in the formula, conduct two binary searches over the domain of the variable, one searching for the lower bound, the other for the upper bound. The starting value in the search for each variable is the value for the variable in the solution found in step 1. Use the SMT solver to probe each search value for satisfiability and methodically bracket the bounds for each variable.
Pseudo code for the search functions, assuming integer domain variables:
lower_bound(variable, start, formula)
{
lo = -inf;
hi = start;
last_sat = start;
incr = 1;
do {
variable = (lo + hi) / 2;
if (SMT(formula) == UNSAT) {
lo = variable + incr;
} else {
last_sat = variable;
hi = variable - incr;
}
} while (lo <= hi);
return last_sat;
}
and
upper_bound(variable, start, formula)
{
lo = start;
hi = +inf;
last_sat = start;
do {
variable = (lo + hi) / 2;
if (SMT(formula) == SAT) {
last_sat = variable;
lo = variable + incr;
} else {
hi = variable - incr;
}
} while (lo <= hi);
return last_sat;
}
-inf/+inf are the smallest/largest values representable in the domain of each variable. If lower_bound returns -inf then the variable has no lower bound. If upper_bound returns +inf then the variable has no upper bound.
In practice most of such optimization problems require some sort of iterate-until-maximum/minimum kind of external driver on top of the SMT solver. Quantified approaches are also possible that can leverage the particular capabilities of the SMT solvers, but in practice such constraints end up being too hard for the underlying solver. See this discussion in particular: How to optimize a piece of code in Z3? (PI_NON_NESTED_ARITH_WEIGHT related)
Having said that, most high-level language bindings include the necessary machinery to simplify your life. For instance, if you use the Haskell SBV library to script z3, you can have:
Prelude> import Data.SBV
Prelude Data.SBV> maximize Quantified head 2 (\[x, y] -> x.==3 &&& y.>=1)
Just [3,1]
Prelude Data.SBV> maximize Quantified (head . tail) 2 (\[x, y] -> x.==3 &&& y.>=1)
Nothing
Prelude Data.SBV> minimize Quantified head 2 (\[x, y] -> x.==3 &&& y.>=1)
Just [3,1]
Prelude Data.SBV> minimize Quantified (head . tail) 2 (\[x, y] -> x.==3 &&& y.>=1)
Just [3,1]
The first result states x=3, y=1 maximizes x with respect to the predicate x==3 && y>=1.
The second result says there is no value that maximizes y with respect to the same predicate.
Third call says x=3,y=1 minimizes the predicate with respect to x.
Fourth call says x=3,y=1 minimizes the predicate with respect to y.
(See http://hackage.haskell.org/packages/archive/sbv/0.9.24/doc/html/Data-SBV.html#g:34 for details.)
You can also use the option "Iterative" (instead of Quantified) to have the library do the optimization iteratively instead of using quantifiers. These two techniques are not equivalent as the latter can get stuck in a local minima/maxima, but iterative approaches might solve problems where the quantified version is way too much to handle for the SMT solver.

Big-O of an operation over a single linked list

Suppose you've got a single linked list of size N, and you want to perform an operation on every element, beginning at the end.
I've come up with the following pseudocode:
while N > 0
Current = LinkedList
for 0 to N
Current = Current.tail
end
Operation(Current.head)
N := N-1
end
Now I've got to determine which Big-O this algorithm is.
Supposing that Operation() is O(1), I think it's something like this:
N + (N-1) + (N-2) + ... + (N-(N-1)) + 1
But I'm not sure what Big-O that actually is. I think it is definitely smaller than O(N^2), but I don't think you can say its O(N) either ...
Your equation is basically that of the triangular numbers, and sums to N(N+1)/2. I'll leave you to determine the O() from that!
A quicker way to do this is to construct a new list that is the reverse of the original list, and then perform the operations on that.
Your algorithm is O(n^2) as you suggest in your post. You can do it in O(n), though.
It's important to remember that Big-O notation is an upper bound on the algorithm's time complexity.
1+2+3+...+n = n*(n+1)/2 = 0.5*n^2+O(n)
This is O(n^2), and O(n^2) is tight, i.e. there is no lower runtime order that'd contain your runtime.
A faster algorithm that works from front-to-back could have O(n) instead of O(n^2)
Your runtime analysis is correct, the runtime is 1 + 2 + ... + N which is a sum of the arithmetic progression and therefore = (N²-N) / 2.

Resources