C++ · Course navigation

C++: a perceptron learns OR but not XOR

Train the same neuron on two gates and compare the accuracy it can reach.

On this page
Before you start

C++ arrays and loops.

  • Train the same neuron on two gates and compare the accuracy it can reach.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

A perceptron outputs 1 when a weighted sum of its inputs plus a bias is positive. The learning rule adds rate × error × input to each weight after every example. If the classes can be separated by a straight line, the rule is guaranteed to find such a line.

OR is linearly separable, so the neuron reaches 4 out of 4 correct. XOR is not, because no single line puts (0,1) and (1,0) on one side and (0,0) and (1,1) on the other. The program tracks the best accuracy on XOR over 200 epochs. It can never reach 4 out of 4; in this run it stays at 2.

Code example

C++
#include <algorithm>
#include <iostream>

int train(const int targets[4], int epochs) {
  const int inputs[4][2] = {{0, 0}, {0, 1}, {1, 0}, {1, 1}};
  double w1 = 0, w2 = 0, bias = 0, rate = 0.1;
  int best = 0;
  for (int epoch = 0; epoch < epochs; ++epoch) {
    for (int i = 0; i < 4; ++i) {
      double sum = w1 * inputs[i][0] + w2 * inputs[i][1] + bias;
      int output = sum > 0 ? 1 : 0;
      int error = targets[i] - output;
      w1 += rate * error * inputs[i][0];
      w2 += rate * error * inputs[i][1];
      bias += rate * error;
    }
    int correct = 0;
    for (int i = 0; i < 4; ++i) {
      double sum = w1 * inputs[i][0] + w2 * inputs[i][1] + bias;
      correct += ((sum > 0 ? 1 : 0) == targets[i]);
    }
    best = std::max(best, correct);
  }
  return best;
}

int main() {
  const int or_targets[4] = {0, 1, 1, 1};
  const int xor_targets[4] = {0, 1, 1, 0};
  std::cout << "OR best accuracy: " << train(or_targets, 200) << "/4\n";
  std::cout << "XOR best accuracy: " << train(xor_targets, 200) << "/4\n";
}
Output
OR best accuracy: 4/4
XOR best accuracy: 2/4

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1#include <algorithm>
2#include <iostream>
3
4int train(const int targets[4], int epochs) {
5 const int inputs[4][2] = {{0, 0}, {0, 1}, {1, 0}, {1, 1}};
6 double w1 = 0, w2 = 0, bias = 0, rate = 0.1;
7 int best = 0;
8 for (int epoch = 0; epoch < epochs; ++epoch) {
9 for (int i = 0; i < 4; ++i) {
10 double sum = w1 * inputs[i][0] + w2 * inputs[i][1] + bias;
11 int output = sum > 0 ? 1 : 0;
12 int error = targets[i] - output;
13 w1 += rate * error * inputs[i][0];
14 w2 += rate * error * inputs[i][1];
15 bias += rate * error;
16 }
17 int correct = 0;
18 for (int i = 0; i < 4; ++i) {
19 double sum = w1 * inputs[i][0] + w2 * inputs[i][1] + bias;
20 correct += ((sum > 0 ? 1 : 0) == targets[i]);
21 }
22 best = std::max(best, correct);
23 }
24 return best;
25}
26
27int main() {
28 const int or_targets[4] = {0, 1, 1, 1};
29 const int xor_targets[4] = {0, 1, 1, 0};
30 std::cout << "OR best accuracy: " << train(or_targets, 200) << "/4\n";
31 std::cout << "XOR best accuracy: " << train(xor_targets, 200) << "/4\n";
32}

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
The error is 0 for a correct output, +1 if the neuron should have fired, and −1 if it should not have.—
—
The weights move toward the right answer for this example.—
—
Keep the best accuracy seen after any epoch.—
—
A separating line exists for OR, so training reaches 4/4.—
OR best accuracy: 4/4
No line separates XOR, so training can never reach 4 of 4. Here it never gets above 2.—
OR best accuracy: 4/4
XOR best accuracy: 2/4

Behind the scenes

How C++ processes this code

The C++ compiler produces a native executable. Execution enters main, where objects and function calls perform the work.

Cost and common mistakes

O(epochs · n) time for n examples.

  • Failing to reach 100% on XOR is a property of the model, not a bug or a shortage of epochs.
  • The best accuracy over epochs is shown here; at any single moment the XOR result keeps changing as the weights cycle.

Try it yourself

What do you add to a perceptron to solve XOR?

Reveal answer and reasoning

A hidden layer with a non-linear activation, which gives a multilayer network.

Further reading