C++: a perceptron learns OR but not XOR

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.

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";
}
Read the full lesson