in reply to Send hash of hash arguments to sub
As it has already been said, it seems pointless to use a subroutine in such a case. However, assuming you want to fix your code and understand what's going on, you would need to pass a hash ref, rather than the hash itself, as explained by others above, including kcott. Or another fix would be to put your hash as the last element of your argument list:
my ($source, $target, %hash) = @_;
my $proba = probability($key_level1, $key_level2, %hash);
This way, the hash does not "eat" the trailing arguments.
Update: Corrected a copy_and_paste error and the missing name of the subroutine in the function call. I had to go, I was too hasty on typing this.