The bitwise operations in relation to obtaining Latin squares

05/23/2016 ∙ by Krasimir Yordzhev, et al. ∙ 0

The main thrust of the article is to provide interesting example, useful for students of using bitwise operations in the programming languages C ++ and Java. As an example, we describe an algorithm for obtaining a Latin square of arbitrary order. We will outline some techniques for the use of bitwise operations.

READ FULL TEXT VIEW PDF
POST COMMENT

Comments

There are no comments yet.

Authors

page 1

page 2

page 3

page 4

This week in AI

Get the week's most popular data science and artificial intelligence research sent straight to your inbox every Saturday.

1 Introduction

Let be a positive integer. Throughout denotes the set

Let . We denote by the functions

(1.1)

Then the set can be represented uniquely by the integer

(1.2)

where , is given by formula (1.1). In other words, we will represent each subset of uniquely with the help of an integer from the interval (integer representation of sets).
It is readily seen that

(1.3)

Evidently if , i.e. , then

(1.4)

The empty set is represented by

(1.5)
Definition 1.1.

A Latin square of order is an matrix where each row and each column is a permutation of elements of .

Thus far it is known the number of all Latin squares of order , where [10 , 13 ].
Latin squares and hypercubes have their applications in coding theory, error correcting codes, information security, decision making, statistics, cryptography, conflict-free access to parallel memory systems, experiment planning, tournament design, enumeration and study of H-functions, etc [9 , 8 ].

Definition 1.2.

A matrix is called an exponential Latin square of order if the following conditions hold:

  1. For every there exists such that ;

  2. The matrix is a Latin square of order .

If is a positive integer, then it is readily seen that the set of all Latin squares and the set of all exponential Latin squares are isomorphic.
The use of bitwise operations is a powerful method used in C/C++ and Java programming languages. Unfortunately, in the widespread books on this topic there is incomplete or no description for the work of bitwise operations. The aim of this article is to correct this lapse to a certain extent and present a meaningful example of a programming task, where the use of bitwise operations is appropriate in order to facilitate the work and to increase the effectiveness of the respective algorithm.
Other interesting examples of effective use of bitwise operations can be found in publications [17 ], [15 ] and [16 ].
In this paper we will show that it is easy to create an algorithm for generating random exponential Latin squares of order n using bitwise operations. The presentation of the subsets of the set using the formula (1.2) and the convenience in this case to work with bitwise operations are the basis of the algorithm described by us. Some other algorithms for obtaining random Sudoku matrices and their valuation are described in detail in [2 ], [5 ] and [14 ].

2 Bitwise Operations

The use of bitwise operations is a well-working method, used in programming languages C/C++ and Java. Let us recall the basic definitions related to bitwise operations. More details could be seen, for example, in [1 ], [6 ], [12 ] for the C/C++ programming languages and in [3 ], [11 ] for the Java programming language.
Bitwise operations can be applied for integer data type only. We assume as usual that bit numbering in variables starts from right to left, and that the number of the rightmost one is 0.
Let x,y and z be integer variables or constants of one type, for which bits are needed. Let x and y be initialized (if they are variables) and let the assignment z = x&y; (bitwise AND), or z = x|y; (bitwise inclusive OR), or z = x^y; (bitwise exclusive OR), or z = ~x; (bitwise NOT) be made. For each , the new contents of the -th bit in z will be as it is presented in the Table 1.

Table 1. Bitwise operations

[3mm] -th bit of -th bit of -th bit of -th bit of -th bit of -th bit of x y z = x&y; z = x|y; z = x^y; z = ~x; 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1 0 0

In the case that k is a nonnegative integer, the statement z = x<<k (bitwise shift left) will write in the bit of z the value of the th bit of x, where , and the rightmost bits of x will be filled by zeroes. This operation is equivalent to a multiplication of x by .
The statement z=x>>k (bitwise shift right) works in a similar way. But we must be careful if we use the programming language C or C++, as in various programming environments this operation has different interpretations – sometimes the leftmost bits of z are compulsorily filled by 0 (logical displacement), and elsewhere the leftmost bits of z are filled with the value from the leftmost (sign) bit; i.e. if the number is negative, then the filling will be with 1 (arithmetic displacement). Therefore it’s recommended to use unsigned type of variables (if the opposite is not necessary) while working with bitwise operations. In the Java programming language, this problem is solved by introducing two different operators: z=x>>k and z=x>>>k.

Example 2.1.

To compute the value of the -th bit of an integer variable x we can use the function:

int BitValue(int x, unsigned int i) {
Ψreturn ( (x & 1<<i) == 0 ) ? 0 : 1;
}
Example 2.2.

The next function displays an integer in binary notation. We don’t consider and we don’t display the sign of the integer. For this reason we work with .

void DecToBin(int n)
{
     n = abs(n);
     int b;
     int d = sizeof(int)*8 - 1;
     while ( d>0 && (n & 1<<(d-1) ) == 0 ) d--;
     while (d>=0)
           {
           b= 1<<(d-1) & n ? 1 : 0;
           cout<<b;
           d--;
           }
}
Example 2.3.

The following function calculates the number of 1’s in the binary representation of an integer n. Again we ignore the sign of the number.

int NumbOf_1(int n)
{
     n = abs(n);
     int temp=0;
     int d = sizeof(int)*8 - 1;
     for (int i=0; i<d; i++)
         if (n & 1<<i) temp++;
     return temp;
}
Example 2.4.

Bitwise operations and sets (See also [7 ]). We will use expressions that represent operations with sets in the next section for a description of the algorithm to obtain a random exponential Latin square.

  1. According to formula (1.3), the set is represented by the expression

  2. According to formula (1.4), a singleton is represented by the expression

  3. Let and be two integers, which represent two subsets of . Then the integer that represents their union is represented by the expression

  4. Let . Then, to remove all elements of from , we can do it with the help of the expression

3 Description and Implementation of the Algorithm

We will describe an algorithm created by us, giving the source code written in the C++ programming language with detailed comments.

Algorithm 3.1.
#include <iostream>
#include <cstdlib>
#include <ctime>
#define N 12

using namespace std;

int U = (1<<N) - 1;
    /* U represents the universal set [n] = {1,2, ... ,N}
        according to (1.3) */
int L[N][N];
    /* L- exponential Latin square */

int choice(int k) {
    /* In this case, "choice" means random choice of a 1
       from the binary notation of positive integer k, 0<k<=U */
    if (k<=0 || k>U) {
        cout<<"The choice is not possible \n";
        return 0;
    }
    int id =0;
        /* id - the number of 1 in the binary notation of k */
    for (int i=0; i<N; i++)
        if (k & 1<<i) id++;
    srand(time(0));
    int r = rand()%id+1;
        /* r is a random integer, 1<=r<=id. The function will
            chooses the r-th 1 from the binary notation of k.*/
    int s=0, t=1;
    while (1) {
        if (k&t) s++;
            /* s-th bit of the integer k is equal to 1. */
        if (s==r) return t;
            /* The function returns the integer t=2^{r-1},
                which represents the singleton {r}. */
        t=t<<1;
            /* t=t*2 and check the next bit */
    }
}

void use() {
        /* In this case "use" means "printing" */
    for (int i=0; i<N; i++){
        for (int j=0; j<N; j++)
            cout<<L[i][j]<<" ";
        cout<<endl;
    }
}

int main(int argc, char** argv) {
    int row,col;
    int A;
        /* A represents a subset of [n] according to (1.2) */
    for (row=0; row<N; row++) {
        col =0;
        while (col<N) {
            A=0; /* empty set */
            for (int i=0; i<row; i++) A = A | L[i][col];
            for (int j=0; j<col; j++) A = A | L[row][j];
            A = U ^ A;
                /* The algorithm will select an element of this set
                    and insert it into the next position. */
            if (A!=0) {
                L[row][col] = choice(A);
                col++;
            }
            else col = 0;
        }
    }
    use();
return 0;
}

4 Conclusion

With the help of algorithm 3.1, we received a lot of random exponential Latin squares, for example the next of order 12:

Competing Interests

 Author has declared that no competing interests exist.

References