{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Constrained ordered sum of elements\n\n\nThe objective function of this problem is:\n\n\\begin{align}f(x) = \\sum_{i=1}^{|x|}\\frac{x_i}{i}\\end{align}\n\nFrom a shuffled set of integers, find the numbers that minimize the sum of fractions, so that the sum of the candidates doesn't not surpass 15.\n\nIn this case, the order of the numbers matter, so we use the ``Permutation`` optimizer\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import random\nfrom psopt import Permutation\n\n\ndef main():\n    # define objective function: f([a, b, c, ...]) = a/1 + b/2 + c/3 + ...\n    def obj_func(x):\n        return sum([a / (i + 1) for i, a in enumerate(x)])\n\n    # seed the pseudo-random number generator\n    seed = 5\n    random.seed(seed)\n\n    # list of shuffled candidates ranging from 1 to 50\n    candidates = random.sample(list(range(1, 51)), 50)\n\n    selection_size = 5\n\n    # constraint: sum of values cannot be greater than 18\n    constraint = {\n        \"fn\": sum,\n        \"type\": \">\",\n        \"value\": 18,\n    }\n\n    # instantiate the optimizer\n    def min_sum(particles):\n        return min([sum(i) for i in particles])\n\n    opt = Permutation(obj_func, candidates, constraints=constraint, metrics=[min_sum, 'l2'])\n\n    # define a threshold of acceptance for early convergence\n    threshold = obj_func(sorted(candidates)[:selection_size])\n\n    # minimize the obj function\n    result = opt.minimize(\n        selection_size=selection_size, verbose=1, threshold=threshold, population=20, seed=seed\n    )\n\n    result.history.plot(\"min_sum\")\n    result.history.plot(\"global_best\")\n\n\nif __name__ == \"__main__\":\n    main()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}