LJ goes live


After 7 months I finally feel comfortable to release LJ’s beta version.

The version requires quite and introduction. There are many things to present in LJ since the library seems thin to serve as a support to logic programming within java. But that was one of my guiding lines when I developed LJ – to keep it simple and friendly to use.

Even though it is thin, you will see, if you follow this blog, how using LJ can allow you to do much. Of course that any constrcutive notions, ideas or comments are very welcomed as this is a beta version and I still have some important features (and some les important features) planned out for LJ. I chose to release it now nevertheless since the key ingridient is ready – the logic engine, and I want to start recieving feedback on it as I move on with the rest of the cool features I plan out for you all.

To intreduce LJ I chose to use the very example that led me to develope it. It was in one of my AI classes that I had and assignment to use Prolog to solve the following riddle:

Place the digits 1 through 8 in a 3 by 2 grid with another cell above the middle upper cell and another cell below the middle lower cell in such a way that there won’t be 2 digits that are nambers in the grid and such that one follows each other. So 2 for example, cannot be placed above, under, left or right to 3 or 1.

I wondered at the time on what my instructor said: “Imagine yourself solving this in Java”. So I did. And I realized that even though it will be simple in concept, it will take a lot of lines of code to solve this problem in java. I will have to solve the problem in my application. That is not what Logic Programming is about. Even though it can be slower, sometimes you just care for the solution. Let’s see how simple it is to solve this problem using LJ:

group(1,2,3,4,5,6,7,8);
Variable[] vars = varArray(8);
Integer[] neighbors=new Integer[] {0,2 , 1,2 , 1,4 , 2,3, 2,5 , 3,6 , 4,5 , 5,6 , 5,7};
Constraint[] cons=new Constraint[9];
cons[0]=c(abs,1,vars[0],vars[2]);
for (int i=1; i<9; i++)
           cons[i]=c(cons[i-1],OR,c(abs,1,vars[neighbors[i*2]],vars[neighbors[(i*2)+1]]));
a(r(vars),DIFFER,cons[8]);

Seems odd isn’t it? :) But yes, that’s the entire code. After this the Variables in the array vars will constain all the answers for the puzzle in order (so the indexes 0′s of each var forms the first answer and so on). That’s how Logic Programming works. You just DESCRIBE the problem isntead of solving it. Let’s go through the code and understand what’s going on.

group(1,2,3,4,5,6,7,8);   – this line defines the “players” of the world. In each logical problem you have a domain of possible values. In our case they are the digits 1-8. the LJ command “group” tells the “world” of LJ that from now on 1-8 are related to each other without meaning to order of appearance (this represents all possible permutations on the sequence 1-8 in a single stroke).

Variable[] vars = varArray(8);  - this defines the Variables in which the values of the answer will be placed. In LJ, all queries return false or true if successfuly found an answer and the actual answers are always saved within Variable objects. This way you can create more complicated patterns of queries with simply placing Variables in the arguments of the query. In our case we want all the members of the world (1-8) placed in 8 different variables.

Integer[] neighbors=new Integer[] {0,2 , 1,2 , 1,4 , 2,3, 2,5 , 3,6 , 4,5 , 5,6 , 5,7};   – here we define the problem. If you imagine the grid and number the cells from top-left to bottom-right you will see that teh cell 0 and the cell 2 are neighbors. Then the cells 1 and 2 are neighbors and so on. In the for loop after that we use these indexes to define a constraint.

Constraint[] cons=new Constraint[9];
cons[0]=c(abs,1,vars[0],vars[2]);
for (int i=1; i<9; i++)
           cons[i]=c(cons[i-1],OR,c(abs,1,vars[neighbors[i*2]],vars[neighbors[(i*2)+1]]));
- this defines a Constraint that asks for each pair of neighbors if they are in absolute value of 1 from one another. since we use OR it means that if any pair of neighbors is in absolute 1 from one another then the whole constraint will be true.

a(r(vars),DIFFER,cons[8]);   – “a” meaning “all”, “r” meaning “relate”. This tries to get all the possible relation between vars in such that there’s a sequence of 8 memebrs in the world (“group” provided us with 8! of these) and such that the constraint cons[8] is FALSE (because we use DIFFER). If you look at the for loop in the code, cons[8] hold all the conditions for all the neighbors, so if there’s a permutation that cons[8] is true for, it is not a legit answer for the puzzle. So it’s simply a matter of differing those permutations and get all the rest.

That’s it. LJ turns any problem down to simply these steps:

- Describe your world
- Describe your variables
- Describe your problem
- Query

And that’s only one use of LJ. In future posts and pages I’ll demonstrate more uses.

LJ promises a few things to its users. LJ core classes are immutable making it thread-safe. The lazy evaluation in LJ is thread-safe as well. Yes, you have lazy evaluation :)  you can lazy evaluate permutation of Group, queries on Constraint and even create a Formula Object that will represent infinite countable spaces (LjQ is a Lazy object of such Formula and it represents the rationals field Q).

There are many little methods in LJ that was implemented just to make it extremely comfortable to use. It is far from being perfect or even complete, but I invite you to take a look at this BETA version and contribute ideas and comments to this project as it will grow.

you can find the code of this example inside the Main class as well the LJ’s jar and the java doc of LJ on GitHub: https://github.com/tmkctm/LJ.  LJ has no dependancies. It uses only Java6 libraries. You only need the LJ jar file in your project and you can start enjoying the library’s AI and logic power.

It is recommended that when you use LJ you use “import static LJava.LJ.*;” in your code to fully get the comfort of using LJ without dealing with Java’s sometimes-forcing OOP.

Depends on requests I will add examples that demonstrate the uses of LJ  as well as anouncments on the followed version of the library, so follow this blog and be updated.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s