-
Notifications
You must be signed in to change notification settings - Fork 0
/
Atomizer.cs
118 lines (91 loc) · 4.3 KB
/
Atomizer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using static propcalc.Syntax;
namespace propcalc;
public static class Atomizer {
public static (Deque< Deque<string> >, Deque< (bool, bool) >) atomize(Deque< Deque<string> > bracket) {
Deque< Deque<string> > atomized = new();
Deque< (bool, bool) > atomizedNegs = new();
Deque< Deque<bool> > negInter = removeNegations(bracket);
int intermediate = 0;
// 1 0 2 3 4
// a or b and c | b nor c | 1 xor 2 | a or 3 | 4
// 0 1 0 | 0 1 | 1 0 | 0 0 | 1
for (int i = 0; i < bracket.Size(); ++i) {
Deque<string> whole = bracket[i];
Deque<bool> neg = negInter[i];
if (whole.Size() == 1) { // Single negation, no binary operator
whole.Append(strOf(and));
whole.Append(whole.ReadFirst()); // Idempotence law
neg.Append(neg.ReadFirst()); // Duplicate negation value
}
int operationAmount = neg.Size() - 1;
for (int j = 0; j < operationAmount; ++j) {
var pos = positionOfSignificantOp(whole);
var (atom, atomBool) = cutNextOperation(whole, neg, pos, ref intermediate);
atomized.Append(atom);
atomizedNegs.Append(atomBool);
}
}
return (atomized, atomizedNegs);
}
private static (Deque<string>, (bool, bool)) cutNextOperation(
Deque<string> whole, Deque<bool> booleans, (int, int) positions, ref int intermediate)
{
const int distanceLeftToOp = 2;
const int atomSubParts = 3;
var (operatorPos, boolPos) = positions;
Deque<string> atom = new();
whole.iterator.To(operatorPos - distanceLeftToOp);
for (int i = 0; i < atomSubParts; ++i) {
atom.Append(whole.iterator.GetNext());
whole.iterator.RemoveNext();
}
whole.iterator.AddNext(intermediate++.ToString());
booleans.iterator.To(boolPos);
(bool, bool) linkedBools = (booleans.iterator.Get(), booleans.iterator.GetNext());
booleans.iterator.RemoveNext();
booleans.iterator.Set(false); // Do not negate the resulting clause
return (atom, linkedBools);
}
private static (int, int) positionOfSignificantOp(Deque<string> whole) {
int lowest = int.MaxValue;
int position = undef;
//int boolPosition = undef; boolPositions can be calculated with position / 2
for (int i = 0; i < whole.Size() - 1; ++i) {
if (isIntermediate(whole[i])) {
//++boolPosition;
continue;
}
int opInt = binOpInt(whole[i]);
if (opInt == undef) continue;
if (opInt < lowest) {
lowest = opInt;
position = i;
if (lowest == and)
return (position, position / 2);
}
}
return (position, position / 2);
}
private static Deque< Deque<bool> > removeNegations(Deque< Deque<string> > bracket) {
Deque< Deque<bool> > negationRecord = new();
for (int i = 0; i < bracket.Size(); ++i) {
Deque<string> single = bracket[i];
Deque<bool> negations = new();
for (int j = -1; j < single.Size() - 1; ++j) {
if (isBinOp(single[j + 1]))
continue;
int notCount = 0;
while (single[j + 1].Equals(strOf(not))) {
single.iterator.ToPrev(); // Indexing moved iterator one to the right
single.iterator.RemoveNext();
++notCount;
}
if (!isIntermediate(single[j + 1]))
throw new Exception("Can only negate intermediates.");
negations.Append((notCount & 1) == 1); // Check if intermediate really _is_ negated
}
negationRecord.Append(negations);
}
return negationRecord;
}
}