Heap insert implementation via Dafny (with specifications) - insert

I'm writing HeapInsert in Dafny but I can't prove the correctness of the code.
I tried writing it with this algorithm:
I'm using this algorithm:
heap_size++;
int i = heap_size - 1;
harr[i] = k;
while (i != 0 && harr[parent(i)] <= harr[i])
{
swap(&harr[i], &harr[parent(i)]);
i = parent(i);
}
but I have no idea what is the invariant of the loop, and its pretty hard to prove it.
I need to write the HeapInsert in dafny with specifications and proof.

Related

What is wrong with the recursive algorithm developed for the below problem?

I have tried to solve an algorithmic problem. I have come up with a recursive algorithm to solve the same. This is the link to the problem:
https://codeforces.com/problemset/problem/1178/B
This problem is not from any contest that is currently going on.
I have coded my algorithm and had run it on a few test cases, it turns out that it is counting more than the correct amount. I went through my thought process again and again but could not find any mistake. I have written my algorithm (not the code, but just the recursive function I have thought of) below. Can I please know where had I gone wrong -- what was the mistake in my thought process?
Let my recursive function be called as count, it takes any of the below three forms as the algorithm proceeds.
count(i,'o',0) = count(i+1,'o',0) [+ count(i+1,'w',1) --> iff (i)th
element of the string is 'o']
count(i,'w',0) = count(i+1,'w',0) [+ count(i+2,'o',0) --> iff (i)th and (i+1)th elements are both equal to 'v']
count(i,'w',1) = count(i+1,'w',1) [+ 1 + count(i+2,'w',0) --> iff (i)th and (i+1)th elements are both equal to 'v']
Note: The recursive function calls present inside the [.] (square brackets) will be called iff the conditions mentioned after the arrows are satisfied.)
Explanation: The main idea behind the recursive function developed is to count the number of occurrences of the given sequence. The count function takes 3 arguments:
argument 1: The index of the string on which we are currently located.
argument 2: The pattern we are looking for (if this argument is 'o' it means that we are looking for the letter 'o' -- i.e. at which index it is there. If it is 'w' it means that we are looking for the pattern 'vv' -- i.e. we are looking for 2 consecutive indices where this pattern occurs.)
argument 3: This can be either 1 or 0. If it is 1 it means that we are looking for the 'vv' pattern, having already found the 'o' i.e. we are looking for the 'vv' pattern shown in bold: vvovv. If it is 0, it means that we are searching for the 'vv' pattern which will be the
beginning of the pattern vvovv (shown in bold.)
I will initiate the algorithm with count(0,'w',0) -- it means, we are at the 0th index of the string, we are looking for the pattern 'vv', and this 'vv' will be the prefix of the 'vvovv' pattern we wish to find.
So, the output of count(0,'w',0) should be my answer. Now comes the trouble, for the following input: "vvovooovovvovoovoovvvvovo" (say input1), my program (which is based on the above algorithm) gives the expected answer(= 50). But, when I just append "vv" to the above input to get a new input: "vvovooovovvovoovoovvvvovovv" (say input2) and run my algorithm again, I get 135 as the answer, while the correct answer is 75 (this is the answer the solution code returns). Why is this happening? Where had I made an error?
Also, one more doubt is if the output for the input1 is 50, then the output for the input2 should be at least twice right -- because all of the subsequences which were present in the input1, will be present in the input2 too and all of those subsequences can also form a new subsequence with the appended 'vv' -- this means we have at least 100 favourable subsequences right?
P.S. This is the link to the solution code https://codeforces.com/blog/entry/68534
This question doesn't need recursion or dynamic programming.
The basic idea is to count how many ws we have before and after each o.
If you have X vs, it means you have X - 1 ws.
Let's use vvvovvv as an example. We know that before and after the o we have 3 vs, which means 2 ws. To evaluate the answer, just multiply 2x2 = 4.
For each o we find, we just need to multiply the ws before and after it, sum it all and this is our answer.
We can find how many ws there are before and after each o in linear time.
#include <iostream>
using namespace std;
int convert_v_to_w(int v_count){
return max(0, v_count - 1);
}
int main(){
string s = "vvovooovovvovoovoovvvvovovvvov";
int n = s.size();
int wBefore[n];
int wAfter[n];
int v_count = 0, wb = 0, wa = 0;
//counting ws before each o
int i = 0;
while(i < n){
v_count = 0;
while(i < n && s[i] == 'v'){
v_count++;
i++;
}
wb += convert_v_to_w(v_count);
if(i < n && s[i] == 'o'){
wBefore[i] = wb;
}
i++;
}
//counting ws after each o
i = n - 1;
while(i >= 0){
v_count = 0;
while(i >= 0 && s[i] == 'v'){
v_count++;
i--;
}
wa += convert_v_to_w(v_count);
if(i >= 0 && s[i] == 'o'){
wAfter[i] = wa;
}
i--;
}
//evaluating answer by multiplying ws before and after each o
int ans = 0;
for(int i = 0; i < n; i++){
if(s[i] == 'o') ans += wBefore[i] * wAfter[i];
}
cout<<ans<<endl;
}
output: 100
complexity: O(n) time and space

Regarding time complexity, big O notation

suppose n1,n2 > k.
Does
O(k(n1+n2-k)) = O(k(max(n1,n2)) ?
Also, does
O(n1+n2) = O(max(n1,n2)) ?
Thanks
Is the claim O(k(n1+n2-k)) = O(k(max(n1,n2)) true?
We know that k < min{n1,n2} - thus:
k(n1+n2-k) = k(max{n1,n2} + min{n1,n2} -k) > k(max{n1,n2})
So, it is pretty trivially to show that O(k(max(n1,n2)) is a subset of O(k(n1+n2-k))
We also need to show the other way around, which is also pretty easy because 2k*max{n1,n2} is in O(k(max(n1,n2)), and
k(n1+n2-k) < k(max{n1,n2} + max{n1,n2}) -k) <
< k(max{n1,n2} + max{n1,n2}))
= 2 k*max{n1,n2}
So, the claim is correct.
Does O(n1+n2) = O(max(n1,n2)) ?
This is correct. Since max{n1,n2} <= n1+n2 <= 2*max{n1,n2}, and we don't care about constants when analyzing big O notation.

portfolio optimization sorting efficient solutions C#

I have the following problem to solve:
Let H be a set of portfolios. For each portfolio i in H let (ri,vi) be the (return,risk) values for this solution.
For each i in H if there exists j in H (j is different from i) such that rj>=ri and vj<=vi then delete i from H. because i is dominated by j (it has better return for less risk).
At the end H will be the set of undominated efficient solutions.
I tried to solve the above problem using linq:
H.RemoveAll(x => H.Any(y => x.CalculateReturn() <= y.CalculateReturn() && x.CalculateRisk() >= y.CalculateRisk() && x != y));
But I wonder if there exist a more efficient way, because if H.Count() is of the order of ten thousands, then it takes a lot of time to remove the dominated portfolios.
Thanks in advance for any help !
Christos
First off, you should be caching the Risk/Reward. I can't tell if you are by your code sample, but if you aren't you need to transform the list first.
Once you've done that, it makes sense to order the list according to the risk. As you increase risk, then, all you have to check is that your reward is strictly greater than the best reward you've seen so far. If it's not, you can remove it. That should dramatically improve performance.
Unfortunately, I'm not feeling clever enough to think of a way to do this with pure LINQ at the moment, but this code segment should work:
(Disclaimer: I haven't compiled/tested)
var orderedH = (
from h in H
let reward = h.CalculatedReward()
let risk = h.CalculatedRisk()
orderby risk ascending
select new {
Original = h,
Risk = risk,
Reward = reward
}).ToList();
var maxReward = Double.NegativeInfinity;
for (int i = 0; i < orderedH.Count; i++)
{
if (orderedH[i].Reward <= maxReward) {
orderedH.RemoveAt(i--);
}
else {
maxReward = orderedH[i].Reward;
}
}
var filteredPortfolio = orderedH.Select(h => h.Original);

Probabilistic Sieve of Eratosthenes

Consider the following algorithm.
function Rand():
return a uniformly random real between 0.0 and 1.0
function Sieve(n):
assert(n >= 2)
for i = 2 to n
X[i] = true
for i = 2 to n
if (X[i])
for j = i+1 to n
if (Rand() < 1/i)
X[j] = false
return X[n]
What is the probability that Sieve(k) returns true as a function of k ?
Let's define a series of random variables recursively:
Let Xk,r denote the indicator variable, taking value 1 iff X[k] == true by the end of the iteration in which the variable i took value r.
In order to have fewer symbols and since it makes more intuitive sense with the code, we'll just write Xk,i which is valid although would have been confusing in the definition since i taking value i is confusing when the first refers to the variable in the loop and the latter to the value of the variable.
Now we note that:
P(Xk,i ~ 0) = P(Xk,i-1 ~ 0) + P(Xk,i-1 ~ 1) * P(Xk-1,i-1 ~ 1) * 1/i
(~ is used in place of = just to make it understandable, since = would otherwise take two separate meanings and looks confusing).
This equality holds by virtue of the fact that either X[k] was false at the end of the i iteration either because it was false at the end of the i-1, or it was true at that point, but in that last iteration X[k-1] was true and so we entered the loop and changed X[k] with probability of 1/i. The events are mutually exclusive, so there is no intersection.
The base of the recursion is simply the fact that P(Xk,1 ~ 1) = 1 and P(X2,i ~ 1) = 1.
Lastly, we note simply that P(X[k] == true) = P(Xk,k-1 ~ 1).
This can be programmed rather easily. Here's a javascript implementation that employs memoisation (you can benchmark if using nested indices is better than string concatenation for the dictionary index, you could also redesign the calculation to maintain the same runtime complexity but not run out of stack size by building bottom-up and not top-down). Naturally the implementation will have a runtime complexity of O(k^2) so it's not practical for arbitrarily large numbers:
function P(k) {
if (k<2 || k!==Math.round(k)) return -1;
var _ = {};
function _P(n,i) {
if(n===2) return 1;
if(i===1) return 1;
var $ = n+'_'+i;
if($ in _) return _[$];
return _[$] = 1-(1-_P(n,i-1) + _P(n,i-1)*_P(n-1,i-1)*1/i);
}
return _P(k,k-1);
}
P(1000); // 0.12274162882390949
More interesting would be how the 1/i probability changes things. I.e. whether or not the probability converges to 0 or to some other value, and if so, how changing the 1/i affects that.
Of course if you ask on mathSE you might get a better answer - this answer is pretty simplistic, I'm sure there is a way to manipulate it to acquire a direct formula.

Algorithm for series

A, B, C,…. Z, AA, AB, ….AZ, BA,BB,…. , ZZ,AAA, …., write a function that takes a integer n and returns the string presentation. Can somebody tell me the algorithm to find the nth value in the series?
Treat those strings as numbers in base 26 with A=0. It's not quite an exact translation because in real base 26 A=AA=AAA=0, so you have to make some adjustments as necessary.
Here's a Java implementation:
static String convert(int n) {
int digits = 1;
for (int j = 26; j <= n; j *= 26) {
digits++;
n -= j;
}
String s = "";
for (; digits --> 0 ;) {
s = (char) ('A' + (n % 26)) + s;
n /= 26;
}
return s;
}
This converts 0=A, 26=AA, 702=AAA as required.
Without giving away too much (since this question seems to be a homework problem), what you're doing is close to the same as translating that integer n into base 26. Good luck!
If, as others suspect, this is homework, then this answer probably won't be much help. If this is for a real-world project though, it might make sense to do make a generator instead, which is an easy and idiomatic thing to do in some languages, such as Python. Something like this:
def letterPattern():
pattern = [0]
while True:
yield pattern
pattern[0] += 1
# iterate through all numbers in the list *except* the last one
for i in range(0,len(pattern)-1):
if pattern[i] == 26:
pattern[i] = 0
pattern[i+1] += 1
# now if the last number is 26, set it to zero, and append another zero to the end
if pattern[-1] == 26:
pattern[-1] = 0
pattern.append(0)
Except instead of yielding pattern itself you would reverse it, and map 0 to A, 1 to B, etc. then yield the string. I've run the code above and it seems to work, but I haven't tested it extensively at all.
I hope you'll find this readable enough to implement, even if you don't know Python. (For the Pythonistas out there, yes the "for i in range(...)" loop is ugly and unpythonic, but off the top of my head, I don't know any other way to do what I'm doing here)

Resources