How to read .cnf file in java - java

I have a .cnf file which contains numbers as Conjunctive Normal Form.
I need to read and store them in a data structure (matrix or list) to be able to work with them as index. (I need this to solve a 3-SAT problem.)
How can I read and store them in Java?
c This Formular is generated by mcnf
c
c horn? no
c forced? no
c mixed sat? no
c clause length = 3
c
p cnf 20 91
10 -3 16 0
-8 20 -19 0
2 -6 -20 0
-7 9 3 0
3 15 -14 0
4 15 20 0
11 -9 -6 0
3 -17 19 0
11 5 -12 0
10 3 -15 0
2 15 18 0
-15 12 11 0
18 -19 -8 0
13 20 9 0
11 -10 -14 0
4 18 -9 0
-7 -17 5 0
-7 11 -15 0
6 2 20 0
16 -18 -17 0
4 -13 -20 0
11 17 -8 0
13 -11 -9 0
-11 13 19 0
12 -19 14 0
10 -1 -20 0
19 -20 13 0
13 2 11 0
17 19 -18 0
19 -20 -10 0
-18 16 15 0
-18 7 -20 0
1 -14 -17 0
1 -11 -18 0
-18 8 13 0
-8 4 16 0
-10 1 13 0
9 3 -20 0
-13 4 8 0
17 -11 18 0
18 20 2 0
-20 -1 4 0
-19 2 -9 0
-9 -16 -15 0
-2 12 9 0
5 19 6 0
-8 -5 -13 0
-18 20 -6 0
5 -18 12 0
2 5 19 0
-5 -8 -11 0
-20 -17 11 0
-18 -14 -16 0
-3 -18 -7 0
-11 20 17 0
-1 -15 -13 0
9 -5 11 0
-17 -7 -1 0
-6 -1 -16 0
-3 -15 -19 0
17 14 11 0
-17 12 13 0
16 12 -2 0
14 10 -16 0
8 -4 5 0
-5 16 17 0
-18 -1 -15 0
11 -15 -13 0
16 -9 -7 0
-8 -15 2 0
-19 -10 1 0
12 -15 -20 0
13 -10 9 0
17 7 18 0
20 15 -2 0
-6 -7 -1 0
14 11 15 0
18 13 -9 0
-4 -12 -2 0
-13 -5 -9 0
5 13 16 0
20 -14 -15 0
19 -20 18 0
19 -17 13 0
3 19 14 0
6 3 20 0
-8 -20 -2 0
12 -10 -19 0
-2 -5 -8 0
13 -4 -11 0
-5 -10 19 0
%
0

From a birds-view perspective, the CNF reader pseudo code looks like this (in C#):
StreamReader cnf = openReader(fileName);
int noOfVars = 0;
while (!cnf.EndOfStream)
{
line = cnf.ReadLine().Trim();
if (line.Length >= 1)
{
c = line[0];
if ((noOfVars > 0) &&
((c == '-') || ((c >= '0') && (c <= '9'))))
{
Clause cl = new Clause(line);
ListOfClauses.Add(cl);
}
else if (c == 'c')
{
processCStatement(line);
}
else if (c == 'p')
{
processPStatement(line, ref noOfVars, ref noOfClauses);
}
else
{
error("Statement has neither 'c' nor 'p' in first column: " + line[0]);
break;
}
}
}
To construct a Clause object from a CNF line:
public Clause(string line)
{
int id = -1;
string[] arr = line.Split(whitespaceSeparator, StringSplitOptions.RemoveEmptyEntries);
if (arr.Length < 1)
{
raise("Empty clause!");
}
foreach (string s in arr)
{
try
{
id = int.Parse(s);
}
catch (Exception)
{
raise("Invalid literal: " + s);
}
if (id != 0)
{
Literal lit = new Literal(id);
this.Add(lit);
}
}
if (id != 0)
{
raise("Line does not end with '0'");
}
// sort literals and remove duplicates
this.unify();
}
This pseudo code assumes that the CNF ist stored as list of Clause objects. Each Clause is a list of Literal objects. A Literal has a positive variable ID and an inverted or non-inverted polarity.
In terms of performance, it might be better to store the literals as integer arrays (or even bit-sets) rather than as list of objects.

If you want to use the library SAT4J (http://www.sat4j.org/), it will read a .cnf in Java without any problem.
public class Example {
public static void main(String[] args) {
ISolver solver = SolverFactory.newDefault();
Reader reader = new DimacsReader(solver);
// CNF filename is given on the command line
try {
IProblem problem = reader.parseInstance(args[0]);
} catch (FileNotFoundException e) {
} catch (ParseFormatException e) {
} catch (IOException e) {
}
}
}
This library is designed to read and solve CNF formula :). But you can use it just to read as you wanted :).

Related

Reading a file with integers that may or may be delineated by spaces

So I have this file that is filled only with integers. I would like to, if possible, be able to read a file that may or may not have spaces delineating each integer.
Here are two visual examples.
The first one are integers that are not delineated by spaces while the second one are.
First Example:
020030090
000907000
900208005
004806500
607000208
003102900
800605007
000309000
030020050
Second Example:
0 3 8 0 12 0 15 16 6 0 4 0 0 0 0 0
0 11 5 0 1 0 0 14 13 0 3 9 12 7 0 0
0 0 0 0 6 0 0 0 0 12 0 14 0 0 0 16
10 16 0 6 2 13 0 0 0 8 7 0 0 0 0 0
3 10 1 0 13 0 0 15 0 9 0 16 5 0 0 0
0 0 16 0 0 0 0 11 14 0 13 12 0 3 0 0
4 0 7 8 0 0 12 9 0 0 0 0 0 0 11 0
0 6 0 0 16 0 0 0 11 5 0 0 15 0 0 2
11 0 0 12 0 0 8 2 0 0 0 1 0 0 14 0
0 7 0 0 0 0 0 0 3 11 0 0 8 16 0 9
0 0 13 0 3 6 0 7 16 0 0 0 0 11 0 0
0 0 0 2 5 0 14 0 15 0 0 4 0 13 7 1
0 0 0 0 0 14 5 0 0 0 16 2 13 0 8 10
14 0 0 0 8 0 9 0 0 0 0 11 0 0 0 0
0 0 6 15 7 1 0 3 12 0 0 13 0 2 5 0
0 0 0 0 0 15 0 12 1 14 0 3 0 6 16 0
Note:
I would also like to add that the second file might not be delineated by the same amount. This means that one integer could have one space after it and another integer could have 10 spaces after it.
What I have tried:
I have tried using the split("\s+") in combination with the replaceAll("", " ") but this not work in the second example because it would have more spaces and thus the split function would not work.
I have tried using replaceAll(" ", "") like this so that they have no spaces at all. Then I converted the string into a char array but that presented problems with integers greater than one digit(would not work with the second example as well).
Code:
public void initializeGrid(int grid[][], String fileName) throws FileNotFoundException, IOException
{
Scanner read = new Scanner(Paths.get(fileName));
int value;
for (int i = 0; i < ROWS; i++)
{
String line = read.nextLine();
String [] numbers = line.trim().split("\\s+");
for (int j = 0; j < COLUMNS; j++)
{
value = Integer.parseInt(numbers[j]);
grid[i][j] = value;
}
}
}
Following the recommendation of #dnault in the comments above, here's an implementation that uses the Java Collection framework instead of a 2d int array. This approach has an advantage over a 2d array in that the List for each row contains exactly as many entries as needed. Using arrays, if a line has less than COLUMN values, the array will contain zeros for all remaining values.
public List<List<Integer>> readFile(String fileName)
throws FileNotFoundException, IOException {
BufferedReader br = Files.newBufferedReader(Paths.get(fileName));
List<List<Integer>> values = new ArrayList<>();
for(String line; (line = br.readLine()) != null;){
String[] splitLine = line.trim().split("\\s+");
if(splitLine.length < 2)
values.add(parseSingleDigitValues(splitLine[0].toCharArray()));
else
values.add(parseDelimitedValues(splitLine));
}
return values;
}
private List<Integer> parseSingleDigitValues(char[] line) {
List<Integer> values = new ArrayList<>();
for(char c: line){
values.add(Integer.parseInt(String.valueOf(c)));
}
return values;
}
private List<Integer> parseDelimitedValues(String[] line) {
List<Integer> values = new ArrayList<>();
for(String str :line)
values.add(Integer.parseInt(str));
return values;
}
The resulting List<List<Integer>> can then be easily converted into a 2D int array using the following method:
private int[][] asArray(List<List<Integer>> lists){
int s1 = lists.size();
int s2 = 0;
for(List<Integer> sublist : lists){
if(sublist.size() > s2)
s2 = sublist.size();
}
int[][] arr = new int[s1][s2];
for(int i = 0; i < lists.size(); i++){
List<Integer> sublist = lists.get(i);
for(int j = 0; j < sublist.size(); j++){
arr[i][j] = sublist.get(j);
}
}
return arr;
}
EDIT In the end, if you clearly document your code/api then the burden is on the user to put it into proper use. I recommend you opt for simplicity in your API: Tell the user they must provide a space-delimited file. You can then provide a utility class that will convert a non-delimited file into a space-delimited file.

Toeplitz matrix initialization

I am trying to initialize a Toeplitz matrix in java. I want it to have this form
6 -4 1 0 0 ... 0
-4 6 -4 1 0 ... 0
1 -4 6 -4 1 ...0
................
0 ... 1 -4 6 -4 1
0 ... ...1 -4 6-4
0 .. ... 0 1 -4 6
I realized that the problem is in the if(j>i) in the bounds of data[i-j-1] . I tried to change it but i get the IndexOutOfBounds error. Here is the code i've written so far
int a1[][] = new int[size][size];
int data[] = new int[size];
data[0] = 6;
data[1] = -4;
data[2] = 1;
for(int i=3; i<size; i++){
data[i] = 0;
}
/* Creating the A1 matrix */
for(int i=0; i<size; i++)
{
for(int j=0; j<size; j++)
{
if(j>i){
a1[i][j] = data[j-i-1];
}else if(j==i){
a1[i][j] = data[0];
}else{
a1[i][j] = data[i-j-1];
}
}
}
And the output is
The Matrix is :
6 6 -4 1 0 0 0 0 0 0
6 6 6 -4 1 0 0 0 0 0
-4 6 6 6 -4 1 0 0 0 0
1 -4 6 6 6 -4 1 0 0 0
0 1 -4 6 6 6 -4 1 0 0
0 0 1 -4 6 6 6 -4 1 0
0 0 0 1 -4 6 6 6 -4 1
0 0 0 0 1 -4 6 6 6 -4
0 0 0 0 0 1 -4 6 6 6
0 0 0 0 0 0 1 -4 6 6
The problem is if i = j+1 or j = i+1, a1 is assigned a1[i][j] = data[0]. This is an off-by-one mistake, you should remove the 1:
for(int j=0; j<size; j++) {
if(j>i){
a1[i][j] = data[j-i];
}else if(j==i){
a1[i][j] = data[0];
}else{
a1[i][j] = data[i-j];
}
}

Ulam Hypothesis - Minor Error

I'm having a minor problem with a program I'm working on. Everything works out perfectly, except for one tiny part.
public class Prog230b
{
public static void main (String args[])
{
for(int i = 1; i <= 25; i++) //
{
int num = i;
System.out.print("\n" + num + ":");
while(num != 1)
{
if(num % 2 == 0)
num /= 2;
else
num = 3 * num + 1;
System.out.print(EasyFormat.format(num,4,0));
}
}
}
}
EasyFormat is just a reference to an exterior formatting file. Below is my output.
1:
2: 1
3: 10 5 16 8 4 2 1
4: 2 1
5: 16 8 4 2 1
6: 3 10 5 16 8 4 2 1
7: 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
8: 4 2 1
9: 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
10: 5 16 8 4 2 1
11: 34 17 52 26 13 40 20 10 5 16 8 4 2 1
12: 6 3 10 5 16 8 4 2 1
13: 40 20 10 5 16 8 4 2 1
14: 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
15: 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1
16: 8 4 2 1
17: 52 26 13 40 20 10 5 16 8 4 2 1
18: 9 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
19: 58 29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
20: 10 5 16 8 4 2 1
21: 64 32 16 8 4 2 1
22: 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
23: 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1
24: 12 6 3 10 5 16 8 4 2 1
25: 76 38 19 58 29 88 44 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
The problem is that it prints nothing for 1. I know this is because I have while(num != 1), but I am unsure what to put instead that does not result in an infinite loop.
Use a do-while loop instead. That way your code will execute at least one time when num starts as 1.
do
{
if(num % 2 == 0)
num /= 2;
else
num = 3 * num + 1;
System.out.print(EasyFormat.format(num,4,0));
} while (num != 1);

Shifted bits values

String message = "1";
byte[] bytes = message.getBytes();
System.out.println(bytes[0] + ": ");
for (int i = 0; i < 8; i++) {
System.out.print((bytes[0] >> (7 - i)) + " ");
}
Output: 49:
0 0 1 3 6 12 24 49
So my string is 1 which in ASCII is 49. What I'm trying to understand is why do my bits have values 3,6,12,24 and 49? What's happening behind, why aren't they only 0 and 1 like the first 3?
49 in binary is
110001
You shift this same value by 7, 6, 5, 4, ..., (7 - i) bits.
So
00110001 >> 7 ==> 00000000 == 0
00110001 >> 6 ==> 00000000 == 0
00110001 >> 5 ==> 00000001 == 1
00110001 >> 4 ==> 00000011 == 3
...
You can use Integer.toBinaryString(int) to get the binary representation of an integer value as a String.
Because your bit extraction is incorrect. The bit representation for the character '1' is that of 49: 00110001.
You are shifting 7 times, then 6, then 5, etc., but you are not isolating the bits properly.
00110001 >> 7 is 00000000 or 0
00110001 >> 6 is 00000000 or 0
00110001 >> 5 is 00000001 or 1
00110001 >> 4 is 00000011 or 3
00110001 >> 3 is 00000110 or 6
00110001 >> 2 is 00001100 or 12
00110001 >> 1 is 00011000 or 24
00110001 >> 0 is 00110001 or 49
You must do a bitwise-and with 1 to isolate the bit you've shifted to get the 1s and 0s out.
System.out.print( ((bytes[0] >> (7 - i)) & 1) + " ");
Output:
49:
0 0 1 1 0 0 0 1
The last 8 bits of number 49 in binary looks like this:
00110001
When you shift the number right by k bits, it's the same as dividing it in int by 2k. That is what you get in the output (digits to the right of | are dropped):
0 | 0110001 -- 0
00 | 110001 -- 0
001 | 10001 -- 1
0011 | 0001 -- 3
00110 | 001 -- 6
001100 | 01 -- 12
0011000 | 1 -- 24
00110001 | -- 49
When shifting, you shift the bits n positions (in this case to the right).
So:
Loop# 7-i bits result
0 7 000000000 0
1 6 000000000 0
2 5 000000001 1
3 4 000000011 3
4 3 000000110 6
5 2 000001100 12
6 1 000011000 24
7 0 000110001 49
The reason why the first shifts are 0 and 1 is because al significant bits were already shifted out.
If you want to obtain the last bit, you need to perform (a>>s)&1 with a the number and s the bit from right you want.
In case you want to print the binary representation of a, you can simply use Integer.toBinaryString(a);
Your actual data might be 49 but, it needs to fill 8 bit for byte data types.So, if you count 8 bit starting from 0 to 7 (as per your loop).And you are using >> which will right shift.
49 binary is 0 0 1 1 0 0 0 1
0 0 1 1 0 0 0 1 >> 7-0 = 00000000 = 0
0 0 1 1 0 0 0 1 >> 7-1 = 00000000 = 0
0 0 1 1 0 0 0 1 >> 7-2 = 00000001 = 1
0 0 1 1 0 0 0 1 >> 7-3 = 00000011 = 3
0 0 1 1 0 0 0 1 >> 7-4 = 00000110 = 6
0 0 1 1 0 0 0 1 >> 7-5 = 00001100 = 12
0 0 1 1 0 0 0 1 >> 7-6 = 00011000 = 32
0 0 1 1 0 0 0 1 >> 7-7 = 00110001 = 49

How to format an array of integers in java

Currently I have the following method:
public static void printDoubleIntArray(int[][] doubleIntArray) {
for (int x = 0; x < doubleIntArray.length; x++) {
System.out.println();
for (int y = 0; y < doubleIntArray[x].length; y++) {
System.out.print(doubleIntArray[x][y]);
}
}
}
It works perfectly when the parameter "doubleIntArray" is only numbers from 0 - 9 like in the following print out:
0000000
0000300
0033332
0023323
0022223
0023233
0003332
However, if the integers in each element of the array become larger than 9 then I get something like the following:
0000000
000121797
001717171716
0101617171617
001616161617
081617161717
001417171716
What I would like to know is how do I make the above example print out like so:
0 0 0 0 0 0 0
0 0 0 12 17 9 7
0 0 17 17 17 17 16
0 10 16 17 17 16 17
0 0 16 16 16 16 17
0 8 16 17 16 17 17
0 0 14 17 17 17 16
You could try using java.text.NumberFormat and a pattern that displays every number with a fixed width.. Then concatenate them all in a single line...
System.out.print(doubleIntArray[x][y] + "\t");
\t prints a tab
but in this case it will print something like this: (but i guess thats okay for you)
0 0 0 0 0 0 0
0 0 0 12 17 9 7
0 0 17 17 17 17 16
0 10 16 17 17 16 17
0 0 16 16 16 16 17
0 8 16 17 16 17 17
0 0 14 17 17 17 16
Or use String.format("%4d", myinteger) to have each integer occupy 4 chars, and be properly right padded.
System.out.printf("%4d", doubleIntArray[x][y]);
4 represents the minimum space that the number will print.
The other options for this method are explained here
You have 2 options. Firstly, you can use \t in the second for loop. But I think you could add \t and whitespace character to avoid deterioration. Can provide this too, adding if-else structure in second for loop. I mean
if(doubleIntArray[y].length<10){
System.out.print(doubleIntArray[x][y] + "\t ");
//Tab+two whitespace.
} else {
if(doubleIntArray[y].length>10) {
System.out.print(doubleIntArray[x][y] + "\t ");
//Tab+one whitespace
} else {
System.out.print(doubleIntArray[x][y] + "\t");
//Tab+NO whitespace
}
}
Logic is that I think. Sorry for my answers design. I am on the bus now and I cannot write smoothly. If I had a mistake sorry about that again.
public static void printDoubleIntArray(int[][] doubleIntArray) {
for (int x = 0; x < doubleIntArray.length; x++) {
System.out.println();
for (int y = 0; y < doubleIntArray[x].length; y++) {
System.out.print(doubleIntArray[x][y],"\t");
}
System.out.print("\n");
}
}

Categories