Wednesday, August 31, 2016

Perkun in C++ notation

You may think that the Perkun/Perkun2 syntax is rather odd. I was thinking about a comparison - for example with C++. And I came up with the following example:

variables
{
input variable a:{false,true},b:{false,true},c:{false,true};
output variable action:{false,true};
hidden variable d:{false,true},e:{false,true},f:{false,true};
}

Now imagine the following class in C++-like pseudocode:

class x
{
private:
class hidden { bool d,e,f; };
std::map<hidden,double> distribution;
public:
bool get_decision(bool a, bool b, bool c) const;
};

In other words we have a class with a probability distribution over a cartesian product of the hidden variables and a single function mapping the input variables into (one) output variable. Note that if there were no hidden variables then our distribution would disappear and we would have a stateless class (or simply a function) get_decision.

You might ask what is the benefit of using Perkun rather then simply hard code the function mapping input to output. I think that in simple cases it may be obviously simple to hard code it. But it is a trap. By hard coding it we do not explain the machine WHY the mapping looks so, we only provide it with the end result. We might end up with the hard coded solutions for myriads of different input sets. It might be even so that the idea of telling the machine how to derive the result from simple components (payoff,model) will be treated as highly experimental. Well, Perkun/Perkun2 are highly experimental. In spite of that I think they open intriguing possibilities as new technologies of programming.

BTW. The fact I usually only use a single output variable is a convention. You are free to use multiple output variables.




Tuesday, August 30, 2016

PerkunWars - a simple fantasy game based on Perkun.

I would like to introduce a small project you can download from https://sourceforge.net/projects/perkunwars/ - PerkunWars - a simple fantasy game.

In the game there is one player (Valder), three NPCs (Thragos, Dorban, Pregor) and a vampire. There are three locations (Wyzima, Shadizar and Novigrad). Click on a town to move there (you may also use a menu action).

If you meet any NPCs you may chat with them. The chat window will display something like:

Pregor >I was staying here, in Shadizar. The vampire? He is in Wyzima. I am staying here...
Thragos >I was staying here, in Shadizar. The vampire? He may be in Wyzima. He may be in Novigrad. I am staying here...


You may have noticed that Pregor and Thragos are avoiding the vampire. There is one more NPC - Dorban, who is a witcher and therefore is constantly hunting the vampire. You may attack the vampire yourself (garlic and holy water are helpful). But it makes no sense to attack him alone. You should attack him when the NPCs are around.


This simple game is based on Perkun. Open the file src/perkun_wars.cc. You will see the code creating pipes and forks. For each NPC there is a child process created (running the function main_perkun). An instance of object npc is created and it parses the Perkun specification. What is npc? See the file inc/perkun_wars.h. You will see the code:

class npc: public perkun::optimizer_with_all_data

So for each NPC (Dorban, Pregor and Thragos) there is an instance of perkun::optimizer_with_all_data with some redefined virtual functions, parsing a Perkun specification!

Now take a look at the directory perkun/final_code. It contains the Perkun specifications named after the NPCs. Take a look at the perkun/final_code/pregor_general.perkun. Note the payoff function:

payoff
{
set({where_is_Pregor=>place_Wyzima, do_I_see_vampire=>false}, 100.0);
set({where_is_Pregor=>place_Wyzima, do_I_see_vampire=>true}, 0.0);
set({where_is_Pregor=>place_Shadizar, do_I_see_vampire=>false}, 100.0);
set({where_is_Pregor=>place_Shadizar, do_I_see_vampire=>true}, 0.0);
set({where_is_Pregor=>place_Novigrad, do_I_see_vampire=>false}, 100.0);
set({where_is_Pregor=>place_Novigrad, do_I_see_vampire=>true}, 0.0);
}



Now check the payoff for Dorban (the file perkun/final_code/dorban_general.perkun):

payoff
{
set({where_is_Dorban=>place_Wyzima, do_I_see_vampire=>false}, 0.0);
set({where_is_Dorban=>place_Wyzima, do_I_see_vampire=>true}, 100.0);
set({where_is_Dorban=>place_Shadizar, do_I_see_vampire=>false}, 0.0);
set({where_is_Dorban=>place_Shadizar, do_I_see_vampire=>true}, 100.0);
set({where_is_Dorban=>place_Novigrad, do_I_see_vampire=>false}, 0.0);
set({where_is_Dorban=>place_Novigrad, do_I_see_vampire=>true}, 100.0);
}


Did you notice something? Of course the Dorban's payoff function makes him to follow the vampire, while Pregor tries to avoid him. This is how we use the payoff function.

The Dorban's variables are:
variables
{
input variable where_is_Dorban:

{place_Wyzima,place_Shadizar,place_Novigrad};
input variable do_I_see_vampire:{false,true};
output variable action:{do_nothing,goto_Wyzima,goto_Shadizar,goto_Novigrad};
hidden variable where_is_vampire:{place_Wyzima,place_Shadizar,place_Novigrad};
}


Note that we have one hidden variable here - where_is_vampire. Of course Dorban knows where is the vampire if he can see him (i.e. it is impossible for the vampire to be elsewhere when Dorban can see him). This is solved with the command "impossible" in the Dorban's model. But in general it is a hidden variable.





New releases of Perkun and Perkun2. The problem with Perkun2 has been solved!

There is a new release of Perkun (0.1.1) and Perkun2 (0.0.3).
You may download them from https://sourceforge.net/projects/perkun/ and https://sourceforge.net/projects/perkun2/.

In Perkun there are no substantial changes, just a couple new getters. In Perkun2 there is:
  • an extra parameter (agent name) passed to the print_prompt sub in Perl
  • enhanced code to interpret the actions
  • modified procedure loop
Please be warned that I did not test it for more than two agents. In fact I am sure it will get "surprised" when more than two agents are in place. (The term "suprised" has a strictly defined meaning in the world of Perkun).

I am currently trying to implement something similar to https://sourceforge.net/projects/perkunwars/ - a simple game demonstrating how to use both Perkun and Perkun2 in your own projects.

Wednesday, August 24, 2016

What's wrong with Perkun2?

I wish to explain more precisely what is wrong with Perkun2. Imagine a specification:

values {}
agents
{
  agent a1 {}
  agent a2 {}
  ...
  agent an {}
}
interfaces
{
  interface a1 => a2 {}
  ...
  interface an => a1 {}
}

In other words we have n agents performing the actions interchangeably, according to the pattern a1,a2,...,an,a1,a2,...,an,...

Now the algorithm I propose in Perkun2 consists of two parts:
  • how to optimize the actions (output variable values) in order to maximize the expected value of the payload function
  • how to interpret what has actually happened (how to update the belief)
The first part (optimization) seems to work - that is why I decided to publish Perkun2. I overlooked the second part, however, and left the interpretation of the input variables just as it was in Perkun. But in Perkun2 there are multiple agents. Even though the agent a1 tries to find the optimal action, it is also observing the other agents playing. It is not able to see their decisions directly, but it can observe its input variables as they are changing. For example after the agent's a2 move the input variables of the agent a1 may have changed. The same holds for agent a3,..., up to an. So the first agent is looking for the optimal action only once (on his own move), but is observing the game n times (he is observing what happens after his own move as well as what happens after his opponents moves). Note that a1 can only see HIS input variables, which may be hidden for the agents a2,...,an.

What is a little problematic is the fact that the agent ai (i>1) has the model and payload defined in terms of his own variables. Quite logical. We have to use the interfaces to map these variables into the ones observable by the agent a1.

I am sorry about the trouble again. I will try to fix it. I started with the small improvement passing the current agent name to the print_prompt sub. For example you may type:

<<PERL
$$Perkun2::Optimizer::optimizer{print_prompt} =
    sub
    {
        my ($this, $agent_name) = @_;
        print "SUPER PERKUN2 (", $agent_name, ")> ";
    };
   
PERL


(This enhancement is not published yet!) This way the Perkun2 will ask for input variables before the agents moves:

SUPER PERKUN2 (a1)>
SUPER PERKUN2 (a2)>
...
SUPER PERKUN2 (an)>
SUPER PERKUN2 (a1)>
SUPER PERKUN2 (a2)>
...

But it will find the optimal decision only for the agent a1 (even though it is observing the game for all agents).



Friday, August 19, 2016

WARNING: Perkun2 contains a bug!

There is a serious bug in Perkun2. It fails to interpret the input variables values properly when multiple agents are in place. I created a model for two players and found out that Perkun2 always gets "surprised".

I am very sorry about the bug, I will try to fix it.

The optimization itself seems to work properly.

Sunday, August 7, 2016

Perkun 0.1.0 and Perkun2 0.0.2 released!

I have released Perkun 0.1.0. There are some changes in the Perkun's behaviour:
  • the default model and default payoff function are filled with zeros
  • the test_model code is disabled
  • the Prolog generators are better (they skip the zeros in menu set thus producing smaller Perkun code) 
I have also noticed that there were some clashes in the function naming making it impossible to use both Perkun and Perkun2 as libraries. I fixed the problem releasing new Perkun2 - the version 0.0.2! I have checked that using the Perkun and Perkun2 as libraries (at the same time) works now.