Skip to content

Commit 622e2a3

Browse files
committed
Merge branch 'java'
2 parents 1712466 + 53f46ad commit 622e2a3

File tree

10 files changed

+511
-12
lines changed

10 files changed

+511
-12
lines changed

.github/workflows/ci.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,17 @@ jobs:
9898
- name: Tests
9999
working-directory: Go
100100
run: bats test.bats
101+
102+
java:
103+
runs-on: ubuntu-latest
104+
steps:
105+
- uses: actions/checkout@v3
106+
- name: Setup
107+
run: |
108+
sudo npm install -g bats
109+
- name: Build
110+
working-directory: Java
111+
run: make jar
112+
- name: Tests
113+
working-directory: Java
114+
run: bats test.bats

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
semeion.data
2+
Java/Main.jar
3+
Java/out

CSharp/Program.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2323
using static Neural.Logical;
2424

2525
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
26-
if (args[0] == "--logical")
26+
if (args.FirstOrDefault() == "--logical")
2727
{
2828
var trainingData = Enumerable.Range(0, 2)
2929
.SelectMany(x => Enumerable.Range(0, 2), (l, r) => (l, r))
@@ -66,7 +66,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6666
};
6767
Console.WriteLine($"network: {networkVals.ToJson()}");
6868
}
69-
else if (args[0] == "--semeion")
69+
else if (args.FirstOrDefault() == "--semeion")
7070
{
7171
// --semeion <file> hiddens epochs lr
7272
const int inputCount = 16 * 16;
@@ -128,6 +128,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
128128
Console.WriteLine();
129129
}
130130
}
131+
else {
132+
Console.WriteLine("Specify --logical or --semeion <file>");
133+
}
131134

132135
namespace Neural
133136
{

Java/Makefile

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
##
2+
# source directory
3+
##
4+
SRC_DIR := src
5+
6+
##
7+
# output directory
8+
##
9+
OUT_DIR := out
10+
11+
##
12+
# sources
13+
##
14+
SRCS := $(wildcard $(SRC_DIR)/*.java)
15+
16+
##
17+
# classes
18+
##
19+
CLS := $(SRCS:$(SRC_DIR)/%.java=$(OUT_DIR)/%.class)
20+
21+
##
22+
# compiler and compiler flags
23+
##
24+
JC := javac
25+
JCFLAGS := -d $(OUT_DIR)/ -cp $(SRC_DIR)/
26+
J := java
27+
28+
##
29+
# suffixes
30+
##
31+
.SUFFIXES: .java
32+
33+
##
34+
# targets that do not produce output files
35+
##
36+
.PHONY: all clean
37+
38+
##
39+
# default target(s)
40+
##
41+
all: run
42+
43+
$(CLS): $(OUT_DIR)/%.class: $(SRC_DIR)/%.java
44+
$(JC) $(JCFLAGS) $<
45+
46+
##
47+
# jar
48+
##
49+
jar: $(CLS)
50+
jar cfe Main.jar Main -C out .
51+
52+
##
53+
# run
54+
##
55+
run: jar
56+
$(J) -jar Main.jar
57+
58+
##
59+
# clean up any output files
60+
##
61+
clean:
62+
rm -f $(OUT_DIR)/*.class
63+
rm -f Main.jar

Java/src/CustomRandom.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
Licensed under the MIT License given below.
3+
Copyright 2024 Daniel Lidstrom
4+
Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
this software and associated documentation files (the “Software”), to deal in
6+
the Software without restriction, including without limitation the rights to
7+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8+
the Software, and to permit persons to whom the Software is furnished to do so,
9+
subject to the following conditions:
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
14+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
16+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18+
*/
19+
20+
import java.util.function.Supplier;
21+
22+
public class CustomRandom implements Supplier<Double> {
23+
final int P = 2147483647;
24+
final int A = 16807;
25+
int current = 1;
26+
27+
public Double get() {
28+
current = Integer.remainderUnsigned(current * A, P);
29+
double result = (double)current / P;
30+
return result;
31+
}
32+
}

Java/src/Main.java

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
Licensed under the MIT License given below.
3+
Copyright 2024 Daniel Lidstrom
4+
Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
this software and associated documentation files (the “Software”), to deal in
6+
the Software without restriction, including without limitation the rights to
7+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8+
the Software, and to permit persons to whom the Software is furnished to do so,
9+
subject to the following conditions:
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
14+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
16+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18+
*/
19+
20+
import java.util.Arrays;
21+
import java.util.Locale;
22+
import java.util.Random;
23+
import java.util.function.Supplier;
24+
25+
public class Main {
26+
public static void main(String[] args) {
27+
CustomRandom random = new CustomRandom();
28+
Supplier<Double> rand = () -> random.get();
29+
var trainingData = Arrays.asList(
30+
new DataItem(new double[]{0, 0}, new double[]{Logical.xor(0, 0), Logical.xnor(0, 0), Logical.or(0, 0), Logical.and(0, 0), Logical.nor(0, 0), Logical.nand(0, 0)}),
31+
new DataItem(new double[]{0, 1}, new double[]{Logical.xor(0, 1), Logical.xnor(0, 1), Logical.or(0, 1), Logical.and(0, 1), Logical.nor(0, 1), Logical.nand(0, 1)}),
32+
new DataItem(new double[]{1, 0}, new double[]{Logical.xor(1, 0), Logical.xnor(1, 0), Logical.or(1, 0), Logical.and(1, 0), Logical.nor(1, 0), Logical.nand(1, 0)}),
33+
new DataItem(new double[]{1, 1}, new double[]{Logical.xor(1, 1), Logical.xnor(1, 1), Logical.or(1, 1), Logical.and(1, 1), Logical.nor(1, 1), Logical.nand(1, 1)})
34+
).toArray(new DataItem[0]);
35+
36+
Trainer trainer = Trainer.create(2, 2, 6, rand);
37+
double lr = 1.0;
38+
int ITERS = 4000;
39+
for (int e = 0; e < ITERS; e++) {
40+
var sample = trainingData[e % trainingData.length];
41+
trainer.train(sample.input(), sample.output(), lr);
42+
}
43+
44+
Network network = trainer.network();
45+
System.out.println("Result after " + ITERS + " iterations");
46+
System.out.println(" XOR XNOR OR AND NOR NAND");
47+
for (var sample : trainingData) {
48+
double[] pred = network.predict(sample.input());
49+
System.out.printf(
50+
Locale.ROOT,
51+
"%d,%d = %.3f %.3f %.3f %.3f %.3f %.3f%n",
52+
(int) sample.input()[0], (int) sample.input()[1],
53+
pred[0], pred[1], pred[2], pred[3], pred[4], pred[5]);
54+
}
55+
56+
System.out.println("weights hidden:");
57+
for (int i = 0; i < network.inputCount(); i++) {
58+
for (int j = 0; j < network.hiddenCount(); j++) {
59+
System.out.printf(Locale.ROOT, " %9.6f", network.weightsHidden()[network.inputCount() * i + j]);
60+
}
61+
62+
System.out.printf("\n");
63+
}
64+
65+
System.out.printf("biases hidden:\n");
66+
for (int i = 0; i < network.hiddenCount(); i++) {
67+
System.out.printf(Locale.ROOT, " %9.6f", network.biasesHidden()[i]);
68+
}
69+
70+
System.out.printf("\n");
71+
72+
System.out.printf("weights output:\n");
73+
for (int i = 0; i < network.hiddenCount(); i++) {
74+
for (int j = 0; j < network.outputCount(); j++) {
75+
System.out.printf(Locale.ROOT, " %9.6f", network.weightsOutput()[i * network.outputCount() + j]);
76+
}
77+
78+
System.out.printf("\n");
79+
}
80+
81+
System.out.printf("biases output:\n");
82+
for (int i = 0; i < network.outputCount(); i++) {
83+
System.out.printf(Locale.ROOT, " %9.6f", network.biasesOutput()[i]);
84+
}
85+
86+
System.out.printf("\n");
87+
}
88+
89+
public static class DataItem {
90+
private final double[] input;
91+
private final double[] output;
92+
93+
public DataItem(double[] input, double[] output) {
94+
this.input = input;
95+
this.output = output;
96+
}
97+
98+
public double[] input() {
99+
return input;
100+
}
101+
102+
public double[] output() {
103+
return output;
104+
}
105+
}
106+
107+
public static class Logical {
108+
public static int xor(int a, int b) {
109+
return a ^ b;
110+
}
111+
112+
public static int xnor(int a, int b) {
113+
return 1 - xor(a, b);
114+
}
115+
116+
public static int or(int a, int b) {
117+
return a | b;
118+
}
119+
120+
public static int and(int a, int b) {
121+
return a & b;
122+
}
123+
124+
public static int nand(int a, int b) {
125+
return 1 - and(a, b);
126+
}
127+
128+
public static int nor(int a, int b) {
129+
return 1 - or(a, b);
130+
}
131+
}
132+
}

Java/src/Network.java

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
Licensed under the MIT License given below.
3+
Copyright 2024 Daniel Lidstrom
4+
Permission is hereby granted, free of charge, to any person obtaining a copy of
5+
this software and associated documentation files (the “Software”), to deal in
6+
the Software without restriction, including without limitation the rights to
7+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8+
the Software, and to permit persons to whom the Software is furnished to do so,
9+
subject to the following conditions:
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
14+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
16+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18+
*/
19+
20+
public class Network {
21+
int inputCount;
22+
int hiddenCount;
23+
int outputCount;
24+
double[] weightsHidden;
25+
double[] biasesHidden;
26+
double[] weightsOutput;
27+
double[] biasesOutput;
28+
29+
public Network(
30+
int inputCount,
31+
int hiddenCount,
32+
int outputCount,
33+
double[] weightsHidden,
34+
double[] biasesHidden,
35+
double[] weightsOutput,
36+
double[] biasesOutput) {
37+
this.inputCount = inputCount;
38+
this.hiddenCount = hiddenCount;
39+
this.outputCount = outputCount;
40+
this.weightsHidden = weightsHidden;
41+
this.biasesHidden = biasesHidden;
42+
this.weightsOutput = weightsOutput;
43+
this.biasesOutput = biasesOutput;
44+
}
45+
46+
public int inputCount() {
47+
return inputCount;
48+
}
49+
50+
public int hiddenCount() {
51+
return hiddenCount;
52+
}
53+
54+
public int outputCount() {
55+
return outputCount;
56+
}
57+
58+
public double[] weightsHidden() {
59+
return weightsHidden;
60+
}
61+
62+
public double[] biasesHidden() {
63+
return biasesHidden;
64+
}
65+
66+
public double[] weightsOutput() {
67+
return weightsOutput;
68+
}
69+
70+
public double[] biasesOutput() {
71+
return biasesOutput;
72+
}
73+
74+
public double[] predict(double[] input) {
75+
double[] yHidden = new double[hiddenCount];
76+
double[] yOutput = new double[outputCount];
77+
return predict(input, yHidden, yOutput);
78+
}
79+
80+
public double[] predict(double[] input, double[] yHidden, double[] yOutput) {
81+
for (int c = 0; c < hiddenCount; c++) {
82+
double sum = 0.0;
83+
for (int r = 0; r < inputCount; r++) {
84+
sum += input[r] * weightsHidden[r * hiddenCount + c];
85+
}
86+
87+
yHidden[c] = ActivationFunctions.sigmoid(sum + biasesHidden[c]);
88+
}
89+
90+
for (int c = 0; c < outputCount; c++) {
91+
double sum = 0.0;
92+
for (int r = 0; r < hiddenCount; r++) {
93+
sum += yHidden[r] * weightsOutput[r * outputCount + c];
94+
}
95+
96+
yOutput[c] = ActivationFunctions.sigmoid(sum + biasesOutput[c]);
97+
}
98+
99+
return yOutput;
100+
}
101+
102+
public static class ActivationFunctions {
103+
public static double sigmoid(double f) {
104+
return 1.0 / (1.0 + Math.exp(-f));
105+
}
106+
107+
public static double sigmoidPrim(double f) {
108+
return f * (1.0 - f);
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)