Parcourir la source

add of QAP problem example into documentation

Jérôme BUISINE il y a 3 ans
Parent
commit
74491c1d9b

+ 1 - 1
docs/source/_static/css/custom.css

@@ -31,7 +31,7 @@ footer a {
     color: #009900 !important;   
 }
 
-colgroup :first-child {
+div[id=api] colgroup :first-child {
     width: 60% !important;
 }
 

BIN
docs/source/_static/examples/qap/factories_qap.png


BIN
docs/source/_static/logo_macop.png~


+ 3 - 2
docs/source/conf.py

@@ -25,9 +25,9 @@ copyright = '2021, Jérôme BUISINE'
 author = 'Jérôme BUISINE'
 
 # The short X.Y version
-version = '1.0.8'
+version = '1.0.9'
 # The full version, including alpha/beta/rc tags
-release = 'v1.0.8'
+release = 'v1.0.9'
 
 
 # -- General configuration ---------------------------------------------------
@@ -47,6 +47,7 @@ extensions = [
     'sphinx.ext.autosummary',
     'sphinx.ext.viewcode',
     'sphinx.ext.coverage',
+    #'sphinx.ext.pngmath',
     #'autoapi.extension' 
 ]
 

+ 1 - 5
docs/source/contributing.rst

@@ -8,10 +8,6 @@ Contributing
 Using GitHub
 ------------
 
-This git project uses git-flow_ implementation. You are free to contribute to it.
-
-.. _git-flow: https://danielkummer.github.io/git-flow-cheatsheet/
-
 Please refer to the guidelines_ file if you want more information about process!
 
-.. _guidelines: https://github.com/prise-3d/macop/blob/master/CONTRIBUTING.md 
+.. _guidelines: https://github.com/prise-3d/macop/blob/master/CONTRIBUTING

+ 2 - 2
docs/source/documentations/algorithms.rst

@@ -9,7 +9,7 @@ Find local and global optima
 Overall, in an optimization process, we will seek to find the best, or the best solutions that minimize or maximize our objective function (fitness score obtained) in order to respond to our problem.
 
 .. image:: ../_static/documentation/search_space.png
-   :width:  800 px
+   :width:  95 %
    :align: center
 
 Sometimes, the search space can be very simple. A local search can provide access to the global optimum as shown in figure (a) above. 
@@ -270,7 +270,7 @@ The way to counter this problem is to allow the algorithm to exit the exploitati
 The idea is to make a leap in the search space in order to find a new local optimum which can be the global optimum. The explained process is illustrated below:
 
 .. image:: ../_static/documentation/search_space_simple.png
-   :width:  400 px
+   :width:  45 %
    :align: center
 
 

Fichier diff supprimé car celui-ci est trop grand
+ 7 - 7
docs/source/documentations/introduction.rst


+ 2 - 2
docs/source/documentations/operators.rst

@@ -75,7 +75,7 @@ Mutator operator
 As detailed, the mutation operator consists in having a minimum impact on the current state of our solution. Here is an example of a modification that could be done for our problem.
 
 .. image:: ../_static/documentation/project_knapsack_mutator.png
-   :width:  800 px
+   :width:  90 %
    :align: center
 
 In this example we change a bit value randomly and obtain a new solution from our search space.
@@ -141,7 +141,7 @@ Crossover operator
 Inspired by Darwin's theory of evolution, crossover starts from two solutions to generate a so-called offspring solution composed of the fusion of the data of the parent solutions.
 
 .. image:: ../_static/documentation/project_knapsack_crossover.png
-   :width:  800 px
+   :width:  95%
    :align: center
 
 In this example we merge two solutions with a specific splitting criterion in order to obtain an offspring.

+ 6 - 2
docs/source/documentations/others.rst

@@ -6,11 +6,15 @@ It decomposes the original multi-objective problem into a number of single-objec
 MOEA/D is a state-of-art algorithm in aggregation-based approaches for multi-objective optimization.
 
 .. image:: ../_static/documentation/search_space_moead.png
-   :width:  400 px
+   :width:  45 %
    :align: center
 
 
 As illustrated below, the two main objectives are sub-divised into 5 single-objective optimization sub-problems in order to find the Pareto front.
 
 - ``macop.algorithms.multi.MOSubProblem`` class defines each sub-problem of MOEA/D.
-- ``macop.algorithms.multi.MOEAD`` class exploits ``MOSubProblem`` and implements MOEA/D using weighted-sum of objectives method.
+- ``macop.algorithms.multi.MOEAD`` class exploits ``MOSubProblem`` and implements MOEA/D using weighted-sum of objectives method.
+
+An example with MOEAD for knapsack problem is available in knapsackMultiExample.py_.
+
+.. _knapsackMultiExample.py: https://github.com/jbuisine/macop/blob/master/examples/knapsackMultiExample.py

+ 1 - 1
docs/source/documentations/policies.rst

@@ -12,7 +12,7 @@ Automated operator choice strategies have also been developed in the literature,
 The operator choice problem can be seen as the desire to find the best solution generation operator at the next evaluation that will be the most conducive to precisely improving the solution.
 
 .. image:: ../_static/documentation/operators_choice.png
-   :width:  400 px
+   :width:  45 %
    :align: center
 
 .. note::

+ 2 - 2
docs/source/documentations/problem.rst

@@ -12,7 +12,7 @@ The **knapsack problem** is a problem in combinatorial optimisation: Given a set
 The image below provides an illustration of the problem:
 
 .. image:: ../_static/documentation/knapsack_problem.png
-   :width: 300 px
+   :width: 40 %
    :align: center
 
 
@@ -28,7 +28,7 @@ Problem implementation
 During the whole tutorial, the example used is based on the previous illustration with:
 
 .. image:: ../_static/documentation/project_knapsack_problem.png
-   :width: 600 px
+   :width: 85 %
    :align: center
 
 

+ 1 - 1
docs/source/documentations/solutions.rst

@@ -79,7 +79,7 @@ Knapsack solution
 A valid solution can be shown below where the sum of the object weights is 15 and the sum of the selected objects values is 8 (its fitness):
 
 .. image:: ../_static/documentation/project_knapsack_solution.png
-   :width:  800 px
+   :width:  85 %
    :align: center
 
 Its representation can be translate as a **binary array** with value:

+ 1 - 1
docs/source/documentations/validator.rst

@@ -10,7 +10,7 @@ Validator definition
 An invalid solution can be shown below where the sum of the object weights is greater than 15:
 
 .. image:: ../_static/documentation/project_knapsack_invalid.png
-   :width:  800 px
+   :width:  85 %
    :align: center
 
 In fact, **[1, 0, 1, 0, 0]** is an invalid solution as we have a weight of **16** which violates the knapsack capacity constraint.

Fichier diff supprimé car celui-ci est trop grand
+ 16 - 615
docs/source/examples.rst


+ 155 - 0
docs/source/examples/qap/implementation.rst

@@ -0,0 +1,155 @@
+Macop QAP implementation
+========================
+
+Let's see how it is possible with the use of the **Macop** package to implement and deal with this QAP instance problem.
+
+Solution structure definition
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Firstly, we are going to use a type of solution that will allow us to define the structure of our solutions.
+
+The available ``macop.solutions.discrete.CombinatoryIntegerSolution`` type of solution within the Macop package represents exactly what one would wish for. 
+I.e. a solution that stores a sequence of integers relative to the size of the problem, the order of which is not sorted.
+
+Let's see an example of its use:
+
+.. code:: python
+
+    from macop.solutions.discrete import CombinatoryIntegerSolution
+    
+    solution = CombinatoryIntegerSolution.random(10)
+    print(solution)
+
+
+The resulting solution obtained:
+
+.. code:: bash
+
+    Combinatory integer solution [2 9 8 1 7 6 0 4 3 5]
+
+
+QAP Evaluator
+~~~~~~~~~~~~~
+
+Now that we have the structure of our solutions, and the means to generate them, we will seek to evaluate them.
+
+To do this, we need to create a new evaluator specific to our problem and the relative evaluation function:
+
+- :math:`min_{ϕ∈S_n}\sum_{i=1}^{n}{\sum_{j=1}^{n}{f_{ij}⋅d_{\phi(i)\phi(j)}}}`
+
+So we are going to create a class that will inherit from the abstract class ``macop.evalutarors.base.Evaluator``:
+
+
+.. code:: python
+
+    from macop.evaluators.base import Evaluator
+
+    class QAPEvaluator(Evaluator):
+    """QAP evaluator class which enables to compute QAP solution using specific `_data`
+
+    - stores into its `_data` dictionary attritute required measures when computing a QAP solution
+    - `_data['F']` matrix of size n x n with flows data between facilities (stored as numpy array)
+    - `_data['D']` matrix of size n x n with distances data between locations (stored as numpy array)
+    - `compute` method enables to compute and associate a score to a given QAP solution
+    """
+
+    def compute(self, solution):
+        """Apply the computation of fitness from solution
+
+        Args:
+            solution: {Solution} -- QAP solution instance
+    
+        Returns:
+            {float} -- fitness score of solution
+        """
+        fitness = 0
+        for index_i, val_i in enumerate(solution._data):
+            for index_j, val_j in enumerate(solution._data):
+                fitness += self._data['F'][index_i, index_j] * self._data['D'][val_i, val_j]
+
+        return fitness
+
+The cost function for the quadratic problem is now well defined.
+
+.. warning::
+    The class proposed here, is available in the Macop package ``macop.evaluators.discrete.mono.QAPEvaluator``.
+
+Running algorithm
+~~~~~~~~~~~~~~~~~
+
+Now that the necessary tools are available, we will be able to deal with our problem and look for solutions in the search space of our QAP instance.
+
+Here we will use local search algorithms already implemented in **Macop**.
+
+If you are uncomfortable with some of the elements in the code that will follow, you can refer to the more complete **Macop** documentation_ that focuses more on the concepts and tools of the package.
+
+.. code:: python
+
+    # main imports
+    import numpy as np
+
+    # module imports
+    from macop.solutions.discrete import CombinatoryIntegerSolution
+    from macop.evaluators.discrete.mono import QAPEvaluator
+
+    from macop.operators.discrete.mutators import SimpleMutation
+
+    from macop.policies.classicals import RandomPolicy
+
+    from macop.algorithms.mono import IteratedLocalSearch as ILS
+    from macop.algorithms.mono import HillClimberFirstImprovment
+
+    # usefull instance data
+    n = 100
+    qap_instance_file = 'qap_instance.txt'
+
+    # default validator (check the consistency of our data, i.e. only unique element)
+    def validator(solution):
+        if len(list(solution._data)) > len(set(list(solution._data))):
+            print("not valid")
+            return False
+        return True
+
+    # define init random solution
+    def init():
+        return CombinatoryIntegerSolution.random(n, validator)
+
+    # load qap instance
+    with open(qap_instance_file, 'r') as f:
+        file_data = f.readlines()
+        print(f'Instance information {file_data[0]}')
+
+        D_lines = file_data[1:n + 1]
+        D_data = ''.join(D_lines).replace('\n', '')
+
+        F_lines = file_data[n:2 * n + 1]
+        F_data = ''.join(F_lines).replace('\n', '')
+
+    D_matrix = np.fromstring(D_data, dtype=float, sep=' ').reshape(n, n)
+    print(f'D matrix shape: {D_matrix.shape}')
+    F_matrix = np.fromstring(F_data, dtype=float, sep=' ').reshape(n, n)
+    print(f'F matrix shape: {F_matrix.shape}')
+
+    # only one operator here
+    operators = [SimpleMutation()]
+
+    # random policy even if list of solution has only one element
+    policy = RandomPolicy(operators)
+
+    # use of loaded data from QAP instance
+    evaluator = QAPEvaluator(data={'F': F_matrix, 'D': D_matrix})
+
+    # passing global evaluation param from ILS
+    hcfi = HillClimberFirstImprovment(init, evaluator, operators, policy, validator, maximise=False, verbose=True)
+    algo = ILS(init, evaluator, operators, policy, validator, localSearch=hcfi, maximise=False, verbose=True)
+
+    # run the algorithm
+    bestSol = algo.run(100000, ls_evaluations=100)
+
+    print('Solution score is {}'.format(evaluator.compute(bestSol)))
+
+
+QAP problem solving is now possible with Macop. As a reminder, the complete code is available in the qapExample.py_ file.
+
+.. _qapExample.py: https://github.com/jbuisine/macop/blob/master/examples/qapExample.py
+.. _documentation: https://jbuisine.github.io/macop/_build/html/documentations

+ 24 - 0
docs/source/examples/qap/index.rst

@@ -0,0 +1,24 @@
+Quadratric Assignment Problem
+===============================
+
+This example will deal with the use of the **Macop** package in relation to a quadratic assignment problem (QAP). We will use a known example of this problem to associate a set of facilities (:math:`F`) to a set of locations (:math:`L`).
+
+.. image:: ../../_static/examples/qap/factories_qap.png
+   :width: 50 %
+   :align: center
+   :alt: Example of QAP facilities to locations problem
+
+.. toctree::
+   :maxdepth: 1
+   :numbered:
+   :caption: Contents:
+
+   problem
+   instance
+   implementation
+
+
+.. note:: 
+   The full code for what will be proposed in this example is available: qapExample.py_.
+
+.. _qapExample.py: https://github.com/jbuisine/macop/blob/master/examples/qapExample.py

+ 60 - 0
docs/source/examples/qap/instance.rst

@@ -0,0 +1,60 @@
+QAP Problem instance generation
+===============================
+
+To define a quadratic problem, we will use the available mQAP_ multi-objective quadratic problem generator. 
+
+Genration of the instance
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We will limit ourselves here to a single objective for the purposes of this example. The file **makeQAPuni.cc**, will be used to generate the instance.
+
+
+.. code:: bash
+
+    g++ makeQAPuni.cc -o mQAPGenerator
+    ./mQAPGenerator -n 100 -k 1 -f 30 -d 80 -s 42 > qap_instance.txt
+
+with the following parameters:
+
+- **-n** positive integer: number of facilities/locations;
+- **-k** positive integer: number of objectives;
+- **-f** positive integer: maximum flow between facilities;
+- **-d** positive integer: maximum distance between locations;
+- **-s** positive long: random seed.
+
+The generated qap_instance.txt_ file contains the two matrices :math:`F` and :math:`D` and define our instance problem.
+
+.. _mQAP: https://www.cs.bham.ac.uk/~jdk/mQAP/
+
+.. _qap_instance.txt: https://github.com/jbuisine/macop/blob/master/examples/instances/qap/qap_instance.txt
+
+
+Load data instance
+~~~~~~~~~~~~~~~~~~
+
+
+We are now going to load this instance via a Python code which will be useful to us later on:
+
+.. code:: Python
+
+    qap_instance_file = 'instances/qap/qap_instance.txt'
+
+    n = 100 # the instance size
+
+    with open(qap_instance_file, 'r') as f:
+        file_data = f.readlines()
+        print(f'Instance information {file_data[0]}')
+
+        D_lines = file_data[1:n + 1]
+        D_data = ''.join(D_lines).replace('\n', '')
+
+        F_lines = file_data[n:2 * n + 1]
+        F_data = ''.join(F_lines).replace('\n', '')
+
+    D_matrix = np.fromstring(D_data, dtype=float, sep=' ').reshape(n, n)
+    print(f'D matrix shape: {D_matrix.shape}')
+    F_matrix = np.fromstring(F_data, dtype=float, sep=' ').reshape(n, n)
+    print(f'F matrix shape: {F_matrix.shape}')
+
+.. note::
+    As we know the size of our instance and the structure of the document, it is quite quick to look for the lines related to the :math:`F` and :math:`D` matrices.

+ 70 - 0
docs/source/examples/qap/problem.rst

@@ -0,0 +1,70 @@
+QAP problem definition
+======================
+
+The quadratic assignment problem (QAP) was introduced by Koopmans and Beckman in 1957 in the context of locating "indivisible economic activities". The objective of the problem is to assign a set of facilities to a set of locations in such a way as to minimize the total assignment cost. The assignment cost for a pair of facilities is a function of the flow between the facilities and the distance between the locations of the facilities.
+
+Location assignment example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Consider a **facility location problem** with **four** facilities (and **four** locations). One possible assignment is shown in the figure below: facility 4 is assigned to location 1, facility 1 
+is assigned to location 2, facility 3 is assigned to location 3, and facility 2 is assigned to location 3. This assignment can be written as the permutation :math:`p=\{4,1,3,2\}`, 
+which means that facility 4 is assigned to location 1, facility 1 is assigned to location 2, facility 3 is assigned to location 3, and facility 2 is assigned to location 3. 
+In the figure, the line between a pair of facilities indicates that there is required flow between the facilities, and the thickness of the line increases with the value of the flow. 
+
+.. image:: ../../_static/examples/qap/factories_qap.png
+   :width: 50 %
+   :align: center
+   :alt: Example of QAP facilities to locations problem
+
+
+To calculate the assignment cost of the permutation, the required flows between facilities and the distances between locations are needed.
+
+
+.. tabularcolumns:: |p{1cm}|p{1cm}|p{1cm}|p{1cm}|
+
+.. csv-table:: flow of the current facilities
+   :header: facility `i`, facility `j`, flow( `i`\, `j` )
+   :widths: 2, 2, 3
+
+   1, 4, 4
+   3, 4, 10  
+   3, 1, 8
+   2, 1, 6  
+
+
+.. csv-table:: distances of between locations
+   :header: location `i`, location `j`, distances( `i`\, `j` )
+   :widths: 2, 2, 3
+
+   1, 2, 42
+   1, 3, 30  
+   2, 3, 41
+   3, 4, 23  
+
+
+Then, the assignment cost of the permutation can be computed as:
+
+:math:`f(1,4)⋅d(1,2)+f(3,4)⋅d(1,3)+f(1,3)⋅d(2,3)+f(3,2)⋅d(3,4)` 
+with result :math:`4⋅42+10⋅30+8⋅41+6⋅23=934`.
+
+Note that this permutation is not the optimal solution.
+
+Mathematical definition
+~~~~~~~~~~~~~~~~~~~~~~~
+
+**Sets**
+
+- :math:`N=\{1,2,⋯,n\}`
+- :math:`S_n=\phi:N→N` is the set of all permutations
+
+**Parameters**
+
+- :math:`F=(f_{ij})` is an :math:`n×n` matrix where :math:`f_{ij}` is the required flow between facilities :math:`i` and :math:`j`
+- :math:`D=(d_{ij})` is an :math:`n×n` matrix where :math:`d_{ij}` is the distance between locations :math:`i` and :math:`j`.
+
+**Optimization Problem**
+
+- :math:`min_{ϕ∈S_n}\sum_{i=1}^{n}{\sum_{j=1}^{n}{f_{ij}⋅d_{\phi(i)\phi(j)}}}`
+
+The assignment of facilities to locations is represented by a permutation :math:`\phi`, where :math:`\phi(i)` is the location to which facility :math:`i` is assigned. Each individual product :math:`f_{ij}⋅d_{\phi(i)\phi(j)}` is the cost of assigning facility :math:`i` to location :math:`\phi(i)` and facility :math:`j` to location :math:`\phi(j)`.
+

+ 153 - 0
docs/source/examples/ubqp/implementation.rst

@@ -0,0 +1,153 @@
+Macop UBQP implementation
+=========================
+
+Let's see how it is possible with the use of the **Macop** package to implement and deal with this UBQP instance problem.
+
+Solution structure definition
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Firstly, we are going to use a type of solution that will allow us to define the structure of our solutions.
+
+The available ``macop.solutions.discrete.BinarySolution`` type of solution within the Macop package represents exactly what one would wish for. 
+
+Let's see an example of its use:
+
+.. code:: python
+
+    from macop.solutions.discrete import BinarySolution
+    
+    solution = BinarySolution.random(10)
+    print(solution)
+
+
+The resulting solution obtained:
+
+.. code:: bash
+
+    Binary solution [1 0 1 1 1 0 0 1 1 0]
+
+
+UBQP Evaluator
+~~~~~~~~~~~~~
+
+Now that we have the structure of our solutions, and the means to generate them, we will seek to evaluate them.
+
+To do this, we need to create a new evaluator specific to our problem and the relative evaluation function:
+
+- :math:`min_{ϕ∈S_n}\sum_{i=1}^{n}{\sum_{j=1}^{n}{f_{ij}⋅d_{\phi(i)\phi(j)}}}`
+
+So we are going to create a class that will inherit from the abstract class ``macop.evalutarors.base.Evaluator``:
+
+
+.. code:: python
+
+    from macop.evaluators.base import Evaluator
+
+    class UBQPEvaluator(Evaluator):
+    """UBQP evaluator class which enables to compute UBQP solution using specific `_data`
+
+    - stores into its `_data` dictionary attritute required measures when computing a UBQP solution
+    - `_data['Q']` matrix of size n x n with real values data (stored as numpy array)
+    - `compute` method enables to compute and associate a score to a given UBQP solution
+    """
+
+    def compute(self, solution):
+        """Apply the computation of fitness from solution
+
+        Args:
+            solution: {Solution} -- QAP solution instance
+    
+        Returns:
+            {float} -- fitness score of solution
+        """
+        fitness = 0
+        for index_i, val_i in enumerate(solution._data):
+            for index_j, val_j in enumerate(solution._data):
+                fitness += self._data['F'][index_i, index_j] * self._data['D'][val_i, val_j]
+
+        return fitness
+
+The cost function for the quadratic problem is now well defined.
+
+.. warning::
+    The class proposed here, is available in the Macop package ``macop.evaluators.discrete.mono.QAPEvaluator``.
+
+Running algorithm
+~~~~~~~~~~~~~~~~~
+
+Now that the necessary tools are available, we will be able to deal with our problem and look for solutions in the search space of our QAP instance.
+
+Here we will use local search algorithms already implemented in **Macop**.
+
+If you are uncomfortable with some of the elements in the code that will follow, you can refer to the more complete **Macop** documentation_ that focuses more on the concepts and tools of the package.
+
+.. code:: python
+
+    # main imports
+    import numpy as np
+
+    # module imports
+    from macop.solutions.discrete import CombinatoryIntegerSolution
+    from macop.evaluators.discrete.mono import QAPEvaluator
+
+    from macop.operators.discrete.mutators import SimpleMutation
+
+    from macop.policies.classicals import RandomPolicy
+
+    from macop.algorithms.mono import IteratedLocalSearch as ILS
+    from macop.algorithms.mono import HillClimberFirstImprovment
+
+    # usefull instance data
+    n = 100
+    qap_instance_file = 'qap_instance.txt'
+
+    # default validator (check the consistency of our data, i.e. only unique element)
+    def validator(solution):
+        if len(list(solution._data)) > len(set(list(solution._data))):
+            print("not valid")
+            return False
+        return True
+
+    # define init random solution
+    def init():
+        return CombinatoryIntegerSolution.random(n, validator)
+
+    # load qap instance
+    with open(qap_instance_file, 'r') as f:
+        file_data = f.readlines()
+        print(f'Instance information {file_data[0]}')
+
+        D_lines = file_data[1:n + 1]
+        D_data = ''.join(D_lines).replace('\n', '')
+
+        F_lines = file_data[n:2 * n + 1]
+        F_data = ''.join(F_lines).replace('\n', '')
+
+    D_matrix = np.fromstring(D_data, dtype=float, sep=' ').reshape(n, n)
+    print(f'D matrix shape: {D_matrix.shape}')
+    F_matrix = np.fromstring(F_data, dtype=float, sep=' ').reshape(n, n)
+    print(f'F matrix shape: {F_matrix.shape}')
+
+    # only one operator here
+    operators = [SimpleMutation()]
+
+    # random policy even if list of solution has only one element
+    policy = RandomPolicy(operators)
+
+    # use of loaded data from QAP instance
+    evaluator = QAPEvaluator(data={'F': F_matrix, 'D': D_matrix})
+
+    # passing global evaluation param from ILS
+    hcfi = HillClimberFirstImprovment(init, evaluator, operators, policy, validator, maximise=False, verbose=True)
+    algo = ILS(init, evaluator, operators, policy, validator, localSearch=hcfi, maximise=False, verbose=True)
+
+    # run the algorithm
+    bestSol = algo.run(100000, ls_evaluations=100)
+
+    print('Solution score is {}'.format(evaluator.compute(bestSol)))
+
+
+QAP problem solving is now possible with Macop. As a reminder, the complete code is available in the qapExample.py_ file.
+
+.. _qapExample.py: https://github.com/jbuisine/macop/blob/master/examples/qapExample.py
+.. _documentation: https://jbuisine.github.io/macop/_build/html/documentations

+ 13 - 0
docs/source/examples/ubqp/index.rst

@@ -0,0 +1,13 @@
+Unconstrained Binary Quadratic Programming
+==========================================
+
+This example will be available soon.
+
+.. toctree::
+   :maxdepth: 1
+   :numbered:
+   :caption: Contents:
+
+   problem
+   instance
+   implementation

+ 10 - 0
docs/source/examples/ubqp/instance.rst

@@ -0,0 +1,10 @@
+UBQP Problem instance generation
+================================
+
+
+The four main parameters of the family of mUBQP are:
+
+- ρ: the objective correlation coefficient
+- M: the number of objective functions
+- N: the length of bit strings
+- d: the matrix density (frequency of non-zero numbers)

Fichier diff supprimé car celui-ci est trop grand
+ 18 - 0
docs/source/examples/ubqp/problem.rst


+ 4 - 1
docs/source/index.rst

@@ -8,7 +8,7 @@ Minimalist And Customisable Optimisation Package
 What's **Macop** ?
 ------------------
 
-**Macop** is a discrete optimisation Python package which not which doesn't implement every algorithm in the literature but provides the ability to quickly develop and test your own algorithm and strategies. The main objective of this package is to provide maximum flexibility, which allows for easy experimentation in implementation..
+**Macop** is a discrete optimisation Python package which not which doesn't implement every algorithm in the literature but provides the ability to quickly develop and test your own algorithm and strategies. The main objective of this package is to provide maximum flexibility, which allows for easy experimentation in implementation.
 
 .. toctree::
    :maxdepth: 1
@@ -19,6 +19,9 @@ What's **Macop** ?
    documentations/index
 
    api
+
+   examples
+
    contributing
 
 Indices and tables

+ 202 - 0
examples/instances/qap/qap_instance.txt

@@ -0,0 +1,202 @@
+facilities = 100 objectives = 1 max_distances = 80 max flows = 30 correlation = 0.000000 seed = 42
+ 0 48 19 34 32 75 64 40 66 69 72 20 39 22 19 42 62 10 11 55 76 53 45  3 50 65  6 38 75 71 71 32 27 70 40 17 50 44 24 11 39 65  3 44  9 31 67 47 80 20 42 28 40 23 47 76  6 13 57 76 42 47 27 52 79 54 46 19 12 31 51 48 69 16 17 78 54 17 76 44 19 30  3 56 36 42 75  9 61 61 65 57 44 25 47 55 26 75 50 22 
+48  0 79 18 55 19  5 25 50 39 40 35 73 62 71 49 19 49 28 40 59 21 16 25 42 48 41 25 34  7 79 64 64 30 12 35 67 10 66 51 45 35 66 46 51 69 68 19 16 40 67 60 53 37 16  8 62 49 19 24 27 57 49 30  2 70 17 73 29 19 79 60 58 25 23 39  6 76 18 34 46 62  9 29 20 60 62 12 16 49 68 46 58 45 26 62 67 67  7 68 
+19 79  0  4  9 51 74 27  1 68 27 49 41  9 19 46 65  4 33 69 27 16 39 31 49 22 63 43 36 75  8 47 49 60 71 43 44 58 64 37 30 13 43 51  1 49 55 47 53 78 62 59 10 52 47 72  1 48 49  7 56 40 60 55 10 25 41 12 56 77 76 62 36 28 32 56 48 68 31 74 33 42 77 13  4 39 78 39 64 15 22 54 44 15 67 31 59 38 28 21 
+34 18  4  0 11 58 12 68 20 60  8 52 76 78 10 23 67 63 46 28 29 17 20 57 21 34 50  1 37 45 26 79 55 32 46  3 69  1 27 42 64 30 75  1 66 74 28 76 21 37 10 34 26 64 80 13 49 10 22 75 20 54  7 23 36 66 49 43 63 50 75 24 17 68 44 10 25 30 26 42 21 66 19 57 78 43 79 10  6 32 57 46 12 74 76 55 21 16 15  3 
+32 55  9 11  0 78 35  6  9 43 62 76 79 65 39 47 70 61 77 10 73 35 68 68 73 17 76  5  7  1  8 10 41 46 74 44 66 34 58 46 48 40 62 40 62 24 26 74 61 22 46 11 19  4 74 29 36 15 29 24 60 48 69 37  2 73 24 33 78 77 54  8 26 32 69 43  2  9  7 48 40 24 38 17  8 57 22 59 19 71 11 74 61 38 35  2 41 30 49 15 
+75 19 51 58 78  0 43 35 10 64 61 24 34 61 60 51 11 37 36 76 32 22  9 53 13 24 59 20 79 54  9 72 58 64 73 65 71 31 58 79 73 15 52 10 20 38 29  9  3 65 60 55 75 79 76 20 55 71 35 57 49 21 43 37 48 18 45  4 46 10 42  7 73 35 15 77 75 33 22 30  9 76 25 22 33 16  9 39 55 44  1 46 79  7 42 28  6 13  8 38 
+64  5 74 12 35 43  0 48 22 75 39 58 34 47 56 35 27 45 37 25 22  1 79 35 25 36 70 18 36  6 72 46 12  4 73 31 80 40 50 24 26 76 69 63 78 27 10 25 18 50 35 40 79 71 37 58 28 67 58  6 11 71 33 27 49 16 47 19 57 42 61 64 71 28 54 65 35 29 62 73 28 35 52  7 63 45 15  9  4 16 57 78 50 22 26 13 37 15 80 80 
+40 25 27 68  6 35 48  0 51 11 69 45 72 55 35 22  3 40 32 40 65 40 52 30 48 17 44 22  6 46 19 12 43 36 63 63 30 74 76 57 19 35 20 59 16 65 13 30 40 29 26 37 74 38 13 47  9 34 59 71 20  4 73 24 52 80 60 66 75 36 69 15 53 32 43 61  4 13  9 26 67  1 68 24 49 40 69 66 61 69 70 77 44 61 18 26 46 60 50 73 
+66 50  1 20  9 10 22 51  0 77 20 63 63  4 33 18 64 52 78 23  2  5 37 55 45 18 11 76 37 69  9 53 71 80 61  5 64 31 50  2 13 30 63 65 60  1 59 78 70 32 69  3 72 53 14  7 63 78 27 54 72 47 48 21 72 60  4 35 53 27 12 67  8 53 68 23  8 57 40 58 76 46 35 78 44  8 62 48 35 62 31 78 58 47  3  9 62 30 38  7 
+69 39 68 60 43 64 75 11 77  0 26 55 13 55 64 15 18 21 19 22  2 36 12 53 43 30 25 50 32  6 49 48 46 71 26 80 20  4 64 43 44 62 26 61 73 64 62 37  5 63  4 28 32  3 80 75  8 22  4  4 45 68 41 53 74 24 47 73  1 23 15  3 57 58 16 59 64 68 68 37 16 73 29 40 36 52 33 57 32 18 51 44 34 15 21 38  8 78 76 47 
+72 40 27  8 62 61 39 69 20 26  0 50 69 50 55 28 30 53 44  9 43 60 79 17 42 22 74 47 44 39 70 18 55 21 29 46 39  1 59 11 67 42 12 66  2 45 36 64 43 73 14 20 28 13 54 24 15 63 51 50 69 22 32 24 52 68 49 25 58 20 12 11 21 75 55  5 34 29 38 34 49 75 59 22 49  8 39  4 67 41 77 14 35 35 47 54 20 60 45 16 
+20 35 49 52 76 24 58 45 63 55 50  0 74 55 36 53 20 39  8 17 68 59 78 73 73 19 41 31 53 24 16 57 74 75  7 71  9 68 76  8 46 58 53 78 69 59 28 23 71  1 48 49 75 65 54 21 77 19 65 51 29 45 25 38 52 30 63 73 58 31  7  2 74 77 47 67 51 43 45 66 28 13  5  8 11 26 24 79 55  6 38 52 52 58 20 15 61 58 51 72 
+39 73 41 76 79 34 34 72 63 13 69 74  0 72 42 20 17 32 25 12 28  3 71 13 80 61 10 47 54 37 36 58 80 57 21 32 22  3 51 65  5 11 57  4 18 38 28 60 70 47  8 77  6 19 32 29 26 48 63 30 30 75  8 60 31  6 80 13 45  1 34 15 17 37 24 46 38 25 21 72 30 42 50  3 44 29 13 16 71 35 29 17 42 37 59  9 31 73 52 51 
+22 62  9 78 65 61 47 55  4 55 50 55 72  0 76 64 41 17 43 51 14 31 60 50 18 35 57 30 75 50 39 51 55 19 44 29 69 27 18 27 76 44 34 14 11 66 65 64 78 22 60 44 30 79 35 76 13  7 78 55 25 15 76 30  2 50 47 67 70 56 49 63 49  8 78 21 37 54 64 53 54  7 50 34 73 67 20 25 33 67 50  5 72 22 38 28 77 36 15 46 
+19 71 19 10 39 60 56 35 33 64 55 36 42 76  0 79 23 54 56 75 73  3 65 74 50 57  9 68 68 46 24 15  9 35  3 78 37 56 27 78 12 70 63 45 18 72  3 32 60 50 39 18 77 35 77  4 33 53 74 17  9 34 54  7 35 35 29 46  4 26 65 51 30  1 23 39 10 17 72 41 24 41 23 62 63 25 10 28 44 66 50 58 17 70 78 46 50 13 64 22 
+42 49 46 23 47 51 35 22 18 15 28 53 20 64 79  0 39 56 58 62 47 66 47 43 41 49 75 33 24 22 66  9 28  8 17 24 75 35  2 53 23 22 65 33 37 74 51  8 13 11 40 28 45 71 19 50 31 43 57 59  4 72 61 69 31 61  3 32  7 11 49 74 43 32 70 73 74 76 56 35  8 31 40 41 47  4 56  3 44 65 23 51 69 44 63  8 23 17 51 47 
+62 19 65 67 70 11 27  3 64 18 30 20 17 41 23 39  0 61 24 70 19 28  8  6 53 68 80  6  9 62 60 60 42 60 22 63 55  8  6 74 78  3 39  4 67 49 61 60 36 22  3 10 41 41 35 23 50 68 79 44 50 77  9 47 80 54  8 12 65 22 63 59 28  3 16  9 64 51 35  4 37 34 41 20 78 23  3 61 51 61 68 24 57 77 30 21 56 61 61  4 
+10 49  4 63 61 37 45 40 52 21 53 39 32 17 54 56 61  0 43 72 66  9 74 14 24 44 74 39  7 56 43 50 20 28 35 79 65  1  5 60 58 25 50 36  3 25 72 46 80 37 79 28  9 66 13 47 35 62 26 63 28 59 80 44 67 49 69 53  8 42 49 33 24 39 60  5 10 34 60 15 14 57 46 21 69 40 33 48 72 65 10  7 42  5 45 78 76  6  5  9 
+11 28 33 46 77 36 37 32 78 19 44  8 25 43 56 58 24 43  0 63 38  8 80 36 69 11 64 22 77 69 73  6 38 11 21 62 75 37 59 76 11 62  7 23  1 71 47 52 33 41 71 35 25 48 67 74 70  8  9 58  8 27 64 67 78 47  5 13 17 59 47 22 23 78 23 74 24 24 75 56 40 13 49 16 79 23  4 59 54 35 30 80 63 49 28 22 69 15 16 10 
+55 40 69 28 10 76 25 40 23 22  9 17 12 51 75 62 70 72 63  0 65  5 59 59 57 37 59 75 30 37 47 32  1 44 80  9 38 76 78 29 14 27 39 68 28 57 51 63 47 72  3 64 60 48 59 50 51 41 74 60 35 16 74 26 70 42 71 26 67 52 16 46 16 49 53 60 52 48 14 43 18 17 26 31 61 33 12 69 27 40 61 41 39 49 37 47  3  8 72 58 
+76 59 27 29 73 32 22 65  2  2 43 68 28 14 73 47 19 66 38 65  0 42 72 51 30 70 63 48 70 51 18 24  7 38 60 78 80 66 39  1 53  1 51  4 61  5 77 20 25 51 23  1 20 22 24 51 47 54 67 27 71 70  5 23 15 32 35 80 60 63  4 11 28 71 20 71 71 25 11 28  8 37 48 11 52  7 80 30 69 53 18 74  9 52 76 61 69 52 13 66 
+53 21 16 17 35 22  1 40  5 36 60 59  3 31  3 66 28  9  8  5 42  0 39 73 66 62 68 10 57 14 50 39 37 30 49 50 17 63 42 48  7 31 62 44 74 75 44 12 41 72 30 62 17 38 31 21 18 34 39 27 24  4  4 59 39 72 66 25 12 30  1 11 28  1 12 11 44 70 33 34 23 24 35 26 68 30 76  5  2 65 61 46 74 63  3  3 24 16 73 38 
+45 16 39 20 68  9 79 52 37 12 79 78 71 60 65 47  8 74 80 59 72 39  0 32 32 53 56 16 45 24  9 20 68 62 62 79 77 77 52 54 77  2 70  6 23 61 50 29 47  9 79 12 27 63 39 15 77 40  9 54 18 69 50 41 61 19 19 64 11 37 16 18 49 48 39 20 20 49  4 41 34  9 28 71 35 57  8 11 27 78  6 24 66 38 43 76 68 68 23 46 
+ 3 25 31 57 68 53 35 30 55 53 17 73 13 50 74 43  6 14 36 59 51 73 32  0  8 46 44 62 34  2  2 66  2 64 72 31 80 60 25 53 53 72  7 55 64 33 63 45 74 15 49 19 48 71 41 37 78 53 14  1 63 38 74 28 62 14 31 54 25 25 42 32 72 32 56 25 42 69 13 35 60  5 64 43 26  7 55 57 50 10 43 38 64 45 15 71 30 23 27 74 
+50 42 49 21 73 13 25 48 45 43 42 73 80 18 50 41 53 24 69 57 30 66 32  8  0 16 12  6  3 19 53 20 24 72 37 65 79 17 21 63 20  7 37 12 40 12 54 65  7 71 30 12 23 65  4 36 10  7 51 79 78 75 23 75 76 20 61 78 52 67 31 62 25 13 42 72 72 68 24 65  9 77 17 28 11 71 14 65 74 77 40 18 39 19  6 31 27 69 70 23 
+65 48 22 34 17 24 36 17 18 30 22 19 61 35 57 49 68 44 11 37 70 62 53 46 16  0 23 25 79 55  4 14 54 25 46 23 52 30 15 65  4  6 77 17 19 70 51 14 40 43 12 23 18 24 59 25 44 49 19 64 40 39 26 55  3 56  7 35 23 40 53 43 23 29 73 19 53 24 17 49 11 73 62  7 59  8  5 39 38 27 11 79 26 36 43 32 20  3  2 31 
+ 6 41 63 50 76 59 70 44 11 25 74 41 10 57  9 75 80 74 64 59 63 68 56 44 12 23  0 48 45 75 21 41 49 76  2 48  5 79 70 56 71  9 37 55  6 36 74 28  1 23 24 33 55 65 18 67 22 39 21 42 18 68 25 25 63 60 76 35 59 54 61 13 55 32 19 17 65 76 64 60 68 22  4 13 42 14 19 25 78 48 40  4 31 18  2 42 25 26 61 75 
+38 25 43  1  5 20 18 22 76 50 47 31 47 30 68 33  6 39 22 75 48 10 16 62  6 25 48  0 57 47  4 41 21 50 60 30 78 49 46 62 41 80 38 60 38 22 72 44 25 10 27  2 12 49 63 35 70  8 80 34  9 41 23 13 65  7 16 72 32 65 28 31 53 11 66  9 79 75 40 60 67 63 70 24 20 30 61 45 79 48 47 59 62 46 25 62 47 77 75 32 
+75 34 36 37  7 79 36  6 37 32 44 53 54 75 68 24  9  7 77 30 70 57 45 34  3 79 45 57  0 63 72 54 33 41 25 30 60 38 50  3 61 41 72 26 77 57 26  4 21 49 51 35 28 18 40 30 78 23  8  9 32 74  1 35 66 47 39 71 13 70 51 13 67 48 31 67 24 30 30 73 51 75 43  7 25 37 33 79 30  5 19 20 69 69 38 74 60 77 17 73 
+71  7 75 45  1 54  6 46 69  6 39 24 37 50 46 22 62 56 69 37 51 14 24  2 19 55 75 47 63  0 34 68 75 11 58 28 24 40 31 58 41 69 44 23 52 79 14  8 65 38 15  4 75 30 44 36 51 41 64 23 17 77  1 17 53 38 75 80 34 21 56 28 17 31 60 79 17 61 78  3 61 29  7 12 52 39 24 50 20 54 18  7 36 57 76 16 33 36 69 16 
+71 79  8 26  8  9 72 19  9 49 70 16 36 39 24 66 60 43 73 47 18 50  9  2 53  4 21  4 72 34  0 73 66 55 43 16 50 16 28 12 37 49 15  3 61 42 67 45 40 34  1 30 10 36 69 27 77 76 58 35  1 39 36 44 33 37  8 34 47 47 65 17 36 34 80 58 45 24 72 55 39 62 78 25 33 38 62 15 32 21 19 18 46 19 24 68 73 65 70 29 
+32 64 47 79 10 72 46 12 53 48 18 57 58 51 15  9 60 50  6 32 24 39 20 66 20 14 41 41 54 68 73  0 65 66 68 68 40 56 78 63 66 48 53 49  8  3 76 72  6 63 63 74 40 78  2 62 53 20 72 21 72 47 37 34 51 68 54 74 18 13  7  8 67 10 69 74 71  2 15 46 41 66  7 11 11 15  5 35 53 35 24 30 34 17 48 42 75 26 70 25 
+27 64 49 55 41 58 12 43 71 46 55 74 80 55  9 28 42 20 38  1  7 37 68  2 24 54 49 21 33 75 66 65  0 58 70 73 21 67 36 20 65 80 28 79 72 17 10 65 11 20 46 66 25 48 57 64 69 28 49 32 78 36 59 25 54 77 39 77 56 70 12 47 18 13 31 68  2 17 39 25 32 18 72 15 20 78 69  2 54 76 35 53 78  1 28 14  9 39 76 53 
+70 30 60 32 46 64  4 36 80 71 21 75 57 19 35  8 60 28 11 44 38 30 62 64 72 25 76 50 41 11 55 66 58  0 58 49 24 34 49  7 43 39 18 61 24 43  8 44 47 34 38 49 37 25 29 74 36 27  3 12 63 16  2 20  6 34 34  7 41 39 48 73 51 53 36 55 29 64 18 32 26 75 33 30 60 47  4 26 46 48 10  2 48 72  3 74 32 44 53 38 
+40 12 71 46 74 73 73 63 61 26 29  7 21 44  3 17 22 35 21 80 60 49 62 72 37 46  2 60 25 58 43 68 70 58  0 47 20 60 30  9 61 30 51 31 80 52 51 11 24 71  3 53 35 17 21 54 75 34 41 71 74 31 27 77 73  4 68  7 27 39 10  7 74  2 16 65 47 63  6 27  1 35 11 20 40 52 67 17  5  2  3 16 52 36 27 66 56 62 42 50 
+17 35 43  3 44 65 31 63  5 80 46 71 32 29 78 24 63 79 62  9 78 50 79 31 65 23 48 30 30 28 16 68 73 49 47  0 40 38 65 43 16 45 24  1 64 79 36 38 58  6 19 16 67 36 22 24 23 79 49 17  2 30 64 53 67 76 69 67 66 56 56 69 26 22 38 55 80 69 80  1 23 24 61 71 20 13 61 18 69 10  4 62 28 44 47  1 46 35 33 72 
+50 67 44 69 66 71 80 30 64 20 39  9 22 69 37 75 55 65 75 38 80 17 77 80 79 52  5 78 60 24 50 40 21 24 20 40  0 70  3 76  7 69 55  3  3  3 60 67 65 31  7 14 21 29  6 33 54 76 18 17 18 46 30 25 59 23 69 55 19 68 49 75 61 61 29 73 28 60 18  8 46 60 52 61 45 42 42 77 39  3 37 24 20 40 38 49 40 19 64 32 
+44 10 58  1 34 31 40 74 31  4  1 68  3 27 56 35  8  1 37 76 66 63 77 60 17 30 79 49 38 40 16 56 67 34 60 38 70  0 26 37 47 52 53  6  1 41 37 61  4 33  2  9 13 22 31 80 33 20 52 61 38 46 32 48 26 71 28 52 32  6 37 18 28 71 51  2 17 16 16 17 49 69 72 15 55 33 61 68 67 77 76 22 23  6 15 59 61 58 12 62 
+24 66 64 27 58 58 50 76 50 64 59 76 51 18 27  2  6  5 59 78 39 42 52 25 21 15 70 46 50 31 28 78 36 49 30 65  3 26  0 43 40 48 20 49 11 22 65 18 62 16 48 48 75 59 24 58 13 28 51  4 66 78 44 61 27 42 21 39 37 17 46 58 29  8 64 68 68 40 63 45 44 46 53 58 23 71 66 36 32 40 35 24 55 41 77 64  9 62 72 79 
+11 51 37 42 46 79 24 57  2 43 11  8 65 27 78 53 74 60 76 29  1 48 54 53 63 65 56 62  3 58 12 63 20  7  9 43 76 37 43  0 16 70 52 73 36 37 21  3 32 11 21 10 70 58 77 70 31 48 75 14  8 59  5 17 63  6 77  1  9 38 76 69 16 50  4 51 70 71 79 79 54 78 32 71 80 61 77 60 32 31 57 63 10 78 80 12 61 44 64 62 
+39 45 30 64 48 73 26 19 13 44 67 46  5 76 12 23 78 58 11 14 53  7 77 53 20  4 71 41 61 41 37 66 65 43 61 16  7 47 40 16  0 35 19 31 33 67 10 29 50 77 59  9 76 25 76 38 46 70 47 53 32  4 19 60  3 60 75 37 38 13 28 21 17 57 77 46 72  1 48 22 40 55 64 41 51 57 18 71 42 22 61 30 73 38  7 76 12  7 38 18 
+65 35 13 30 40 15 76 35 30 62 42 58 11 44 70 22  3 25 62 27  1 31  2 72  7  6  9 80 41 69 49 48 80 39 30 45 69 52 48 70 35  0 13 33 50  6 42 53 43 60 50 53 46 30 41 73 11 79  7 26 46 13 10 50 11 30 23 67 64 40 19 13 54 40 14 28 77 70 21 30 17 63 39 64 34 80 79  4 49 46 38 69 51  1 37  2 24 42 48  8 
+ 3 66 43 75 62 52 69 20 63 26 12 53 57 34 63 65 39 50  7 39 51 62 70  7 37 77 37 38 72 44 15 53 28 18 51 24 55 53 20 52 19 13  0 15 37  7 64 45 40 51 41 31 43  5 16  7 75 46  5 10 51 34 74 80 47 48 33 33 42 30 80 80 26 47 76 54 74 45 10 10 21 60 51 22 18 13  6 37 79  1 50 70 37 37 12 63  7 63 15 71 
+44 46 51  1 40 10 63 59 65 61 66 78  4 14 45 33  4 36 23 68  4 44  6 55 12 17 55 60 26 23  3 49 79 61 31  1  3  6 49 73 31 33 15  0 59 36 71 76 78 42 52 37 30  9 15 68 53 65 35 32 59 31 64 63 48 33 34 49 65 23 60 25 59 32 73 62 42 32 20  8 51  5 77 72 58  1 21 44 23 73 35 39 78  2 57 78 40 58 33 79 
+ 9 51  1 66 62 20 78 16 60 73  2 69 18 11 18 37 67  3  1 28 61 74 23 64 40 19  6 38 77 52 61  8 72 24 80 64  3  1 11 36 33 50 37 59  0 45 24 22 11 18 37 24 60 13 10 47 48 80 69  3 44 14 19 16 79 70 43 29 26  9 79 63  9 18  3 75 75  5 75 25  6  7 63 56 35  6 30 59 24 77 11 52 44 25 35 41 64 62 12  2 
+31 69 49 74 24 38 27 65  1 64 45 59 38 66 72 74 49 25 71 57  5 75 61 33 12 70 36 22 57 79 42  3 17 43 52 79  3 41 22 37 67  6  7 36 45  0 52 24 50 55 24 23 68 34 53 28 65 46 69 35 70 47 27 26 75 41 12 37 64 27  5 28 35 48 19 23 64 77 62 15 72 71 59 74  8 63 30 52 38  4  1 36 79 60 46 32 34 63 46 80 
+67 68 55 28 26 29 10 13 59 62 36 28 28 65  3 51 61 72 47 51 77 44 50 63 54 51 74 72 26 14 67 76 10  8 51 36 60 37 65 21 10 42 64 71 24 52  0 45 27 60 59 59 60 60 11 55 26 36  7 10 66 12 69 71  8 10 80 51 54 71 69 63 57 16 32 54 63 40 56 73 46 18 10  6 61 28 29 44 61  1 26 67 44 19 71 67 26 37 60 64 
+47 19 47 76 74  9 25 30 78 37 64 23 60 64 32  8 60 46 52 63 20 12 29 45 65 14 28 44  4  8 45 72 65 44 11 38 67 61 18  3 29 53 45 76 22 24 45  0 16 40 51 68 77 16  7 11 78 46 54 60 73 39 31 24  9 45  9 79 75 76 76 79 16  8 28 60 75 13 64 31 28 47  6 14 69 26 25 31 65 69  2 49 42 32  7 19 16 64 46 33 
+80 16 53 21 61  3 18 40 70  5 43 71 70 78 60 13 36 80 33 47 25 41 47 74  7 40  1 25 21 65 40  6 11 47 24 58 65  4 62 32 50 43 40 78 11 50 27 16  0 10 53 55 76 38 66 62 58 25 26 72 68 39 43  1 72 35  7 14 78  8 22  6 71  7 22 71 37 47 25 12 62 71 60 61 54 38 42 34 64 51 21 21 73 75 74 33 16 14 38 64 
+20 40 78 37 22 65 50 29 32 63 73  1 47 22 50 11 22 37 41 72 51 72  9 15 71 43 23 10 49 38 34 63 20 34 71  6 31 33 16 11 77 60 51 42 18 55 60 40 10  0 11 15 68 69 76 52 70 40 12 64 65 38 72 34 43 15  8 67 10 47 79 51 54  3 12 53 37  8 75 69 40  7 28 31 77  7 34 77 37 28 76 39 64 58 36 33 78 60 55 65 
+42 67 62 10 46 60 35 26 69  4 14 48  8 60 39 40  3 79 71  3 23 30 79 49 30 12 24 27 51 15  1 63 46 38  3 19  7  2 48 21 59 50 41 52 37 24 59 51 53 11  0 75 71 30 27 55 15 54 38 67 62 15  1 66 46 25  9 63 10 18 73 80 17 60 19  6 75 63 20 45  5 71 17 50 46 63 66 66 68 42 34 73 57 54 53 20 57 30  1  3 
+28 60 59 34 11 55 40 37  3 28 20 49 77 44 18 28 10 28 35 64  1 62 12 19 12 23 33  2 35  4 30 74 66 49 53 16 14  9 48 10  9 53 31 37 24 23 59 68 55 15 75  0 12 71 66 80  2 39  5 64  8 62 33 16 31 34 22 70 37 56 10 19  8 31 69 28 56 74 56 69 69 61 53 46 67 28 56 80 14 35 71 71 59 17 69 76 15 73 46 19 
+40 53 10 26 19 75 79 74 72 32 28 75  6 30 77 45 41  9 25 60 20 17 27 48 23 18 55 12 28 75 10 40 25 37 35 67 21 13 75 70 76 46 43 30 60 68 60 77 76 68 71 12  0 61 67 51 36 30 49 49 18 22 14 20 54 38 72 72 29 49 29 66 32 52 58 50 55 25 58 32 38 37 50 50 40 51 35 13 73 72 50 61 57 55 25 80 41 18 32 20 
+23 37 52 64  4 79 71 38 53  3 13 65 19 79 35 71 41 66 48 48 22 38 63 71 65 24 65 49 18 30 36 78 48 25 17 36 29 22 59 58 25 30  5  9 13 34 60 16 38 69 30 71 61  0 72 32 53 58  4 22 43 21 72 50 27 21 52 80 14 34 59 42 60 41 36 19 10 41 58 59 43 68 59 35 18 32  4 59 48 32 17 24 56 69 44 37 46 54 54 34 
+47 16 47 80 74 76 37 13 14 80 54 54 32 35 77 19 35 13 67 59 24 31 39 41  4 59 18 63 40 44 69  2 57 29 21 22  6 31 24 77 76 41 16 15 10 53 11  7 66 76 27 66 67 72  0 61 73 53 41 18 55 74 30 44 63 65 13 50 68 37 24 70 12 58 23 25 40 43 58 65 20 60 34 61  1 70 16 31 78 55  5 38  3 67 26 11 44 13 51 10 
+76  8 72 13 29 20 58 47  7 75 24 21 29 76  4 50 23 47 74 50 51 21 15 37 36 25 67 35 30 36 27 62 64 74 54 24 33 80 58 70 38 73  7 68 47 28 55 11 62 52 55 80 51 32 61  0 52 36 69 15 63  9  2 10 45 43 13 31 13 33 35 29 78 52 20 19 20 34 42 16 61  5 62 62 39  8 41 75  8 38 68 72 31 66 34 35 79 11 70 36 
+ 6 62  1 49 36 55 28  9 63  8 15 77 26 13 33 31 50 35 70 51 47 18 77 78 10 44 22 70 78 51 77 53 69 36 75 23 54 33 13 31 46 11 75 53 48 65 26 78 58 70 15  2 36 53 73 52  0 72 79 24 46 49 50 50 50 70 71  8 35  4 49 29 64  1 21  7 72 22 45 48 64 15 29 75 23  1 61 43 65 34 52 80 71  6 65 43 37  2 13 80 
+13 49 48 10 15 71 67 34 78 22 63 19 48  7 53 43 68 62  8 41 54 34 40 53  7 49 39  8 23 41 76 20 28 27 34 79 76 20 28 48 70 79 46 65 80 46 36 46 25 40 54 39 30 58 53 36 72  0 56 28 20 33 53  2 54 18 72 69  4 41 23 56 58 26 60 39  4 46 45 52 74  7 24 36 46 30 21 13 51 25 43  9 60 26 70 42 21 24 16 47 
+57 19 49 22 29 35 58 59 27  4 51 65 63 78 74 57 79 26  9 74 67 39  9 14 51 19 21 80  8 64 58 72 49  3 41 49 18 52 51 75 47  7  5 35 69 69  7 54 26 12 38  5 49  4 41 69 79 56  0 46 34 48 74 77 26 15 43  2 71 41  3 62 53 23 67 15 31 17 59 23 51 73 24 75 23  7 21 65 56 79 69 39  6 76 38 40 78 17 62 21 
+76 24  7 75 24 57  6 71 54  4 50 51 30 55 17 59 44 63 58 60 27 27 54  1 79 64 42 34  9 23 35 21 32 12 71 17 17 61  4 14 53 26 10 32  3 35 10 60 72 64 67 64 49 22 18 15 24 28 46  0  5 55 55 48 44  4 18 18 61 76 69 28 68 77 65 55 65  5 44 51 11 25 76 51 22 72 68 75 68 58 29 57 29 73 37 79 12 25 60 69 
+42 27 56 20 60 49 11 20 72 45 69 29 30 25  9  4 50 28  8 35 71 24 18 63 78 40 18  9 32 17  1 72 78 63 74  2 18 38 66  8 32 46 51 59 44 70 66 73 68 65 62  8 18 43 55 63 46 20 34  5  0 75 42  2  9 22 77 38 44 18 13 29 33 66 70 54 77 11 31  2 25 41 53 39 28 27 74 32 44 78 32 64 37 35 53 39 66 29 16 22 
+47 57 40 54 48 21 71  4 47 68 22 45 75 15 34 72 77 59 27 16 70  4 69 38 75 39 68 41 74 77 39 47 36 16 31 30 46 46 78 59  4 13 34 31 14 47 12 39 39 38 15 62 22 21 74  9 49 33 48 55 75  0 40 29  8 46 28 80  2 48 16 78 31 33 54 36 27 55 28 12 23 70 43 79 68  2 51 13 41 57 32 15 54 72  9 26 80 40  3 75 
+27 49 60  7 69 43 33 73 48 41 32 25  8 76 54 61  9 80 64 74  5  4 50 74 23 26 25 23  1  1 36 37 59  2 27 64 30 32 44  5 19 10 74 64 19 27 69 31 43 72  1 33 14 72 30  2 50 53 74 55 42 40  0 61 37 14 40 20  3  5 38 64 37 75  4  1 60 78 77 69 56 32 64 39 40 64  9 36 59 41 35 73 76 48 29 14 68 28 72 34 
+52 30 55 23 37 37 27 24 21 53 24 38 60 30  7 69 47 44 67 26 23 59 41 28 75 55 25 13 35 17 44 34 25 20 77 53 25 48 61 17 60 50 80 63 16 26 71 24  1 34 66 16 20 50 44 10 50  2 77 48  2 29 61  0 50 45 45 33 12 41  5 32 76 47 48 52 42 17 50 61 45 38 24  4 12 52 14 71 17 61 44 75 67 54 76 50  9 31 21 61 
+79  2 10 36  2 48 49 52 72 74 52 52 31  2 35 31 80 67 78 70 15 39 61 62 76  3 63 65 66 53 33 51 54  6 73 67 59 26 27 63  3 11 47 48 79 75  8  9 72 43 46 31 54 27 63 45 50 54 26 44  9  8 37 50  0 73 23 74 46 52 11 13 67 66 78 50  7 75  9 28 78 63 80 46 53 60 70 76 58 76 63 51 68 65 35 17 48 15 36 27 
+54 70 25 66 73 18 16 80 60 24 68 30  6 50 35 61 54 49 47 42 32 72 19 14 20 56 60  7 47 38 37 68 77 34  4 76 23 71 42  6 60 30 48 33 70 41 10 45 35 15 25 34 38 21 65 43 70 18 15  4 22 46 14 45 73  0 17 32 27  6 71 11 29 39 73 60 61 58 31 30 72 45  2 51 64  6  2 54 49 58 71 65 79 42 71 42 29 64 71 65 
+46 17 41 49 24 45 47 60  4 47 49 63 80 47 29  3  8 69  5 71 35 66 19 31 61  7 76 16 39 75  8 54 39 34 68 69 69 28 21 77 75 23 33 34 43 12 80  9  7  8  9 22 72 52 13 13 71 72 43 18 77 28 40 45 23 17  0 67 79 29 80 64 56 31 68  1 30 13 78 19 20 36 43 32 25 17 39 62 66 77 62 50 74 76 12 46 50 34 41 17 
+19 73 12 43 33  4 19 66 35 73 25 73 13 67 46 32 12 53 13 26 80 25 64 54 78 35 35 72 71 80 34 74 77  7  7 67 55 52 39  1 37 67 33 49 29 37 51 79 14 67 63 70 72 80 50 31  8 69  2 18 38 80 20 33 74 32 67  0 44 21 42 52 54 40  9 29 33 49 38  5 24  7  6  4 67 17 68 62 37 32 62 29 55 29 16 77 50 36 11 13 
+12 29 56 63 78 46 57 75 53  1 58 58 45 70  4  7 65  8 17 67 60 12 11 25 52 23 59 32 13 34 47 18 56 41 27 66 19 32 37  9 38 64 42 65 26 64 54 75 78 10 10 37 29 14 68 13 35  4 71 61 44  2  3 12 46 27 79 44  0 26 34 24 64 21 11 59 51 25 56 32 49 42 62 52  1 61  4 24 47 29 38 77 25 19 18  7 71 17 53 10 
+31 19 77 50 77 10 42 36 27 23 20 31  1 56 26 11 22 42 59 52 63 30 37 25 67 40 54 65 70 21 47 13 70 39 39 56 68  6 17 38 13 40 30 23  9 27 71 76  8 47 18 56 49 34 37 33  4 41 41 76 18 48  5 41 52  6 29 21 26  0 46 57 32 27  9 31  2 25 54  5 40 37 31 47 38 32 14 17 33 20 51 27  8 47 36 36  4 41 64 27 
+51 79 76 75 54 42 61 69 12 15 12  7 34 49 65 49 63 49 47 16  4  1 16 42 31 53 61 28 51 56 65  7 12 48 10 56 49 37 46 76 28 19 80 60 79  5 69 76 22 79 73 10 29 59 24 35 49 23  3 69 13 16 38  5 11 71 80 42 34 46  0 49 22 60 50 19  9 57 46  6  5  7 76  4 19 11 21 73 34 56 70 15 43 27 37 64 79 79 61 38 
+48 60 62 24  8  7 64 15 67  3 11  2 15 63 51 74 59 33 22 46 11 11 18 32 62 43 13 31 13 28 17  8 47 73  7 69 75 18 58 69 21 13 80 25 63 28 63 79  6 51 80 19 66 42 70 29 29 56 62 28 29 78 64 32 13 11 64 52 24 57 49  0 34 23  2 13 60 11 21 22  3 41  3  7 17 53 75  5 61 27 49 26 65 43 23 55 70 61 12 18 
+69 58 36 17 26 73 71 53  8 57 21 74 17 49 30 43 28 24 23 16 28 28 49 72 25 23 55 53 67 17 36 67 18 51 74 26 61 28 29 16 17 54 26 59  9 35 57 16 71 54 17  8 32 60 12 78 64 58 53 68 33 31 37 76 67 29 56 54 64 32 22 34  0  8 52 34 78 77 24 14 18 18 55 22 27 79 42 43 35 64 19 59 12 17  6 67 40  3 66 37 
+16 25 28 68 32 35 28 32 53 58 75 77 37  8  1 32  3 39 78 49 71  1 48 32 13 29 32 11 48 31 34 10 13 53  2 22 61 71  8 50 57 40 47 32 18 48 16  8  7  3 60 31 52 41 58 52  1 26 23 77 66 33 75 47 66 39 31 40 21 27 60 23  8  0 78 80 10 36 54 39 74 23  2 77 37  8 62 23 48 30 72 69 78 15 52  9 15 48 72 20 
+17 23 32 44 69 15 54 43 68 16 55 47 24 78 23 70 16 60 23 53 20 12 39 56 42 73 19 66 31 60 80 69 31 36 16 38 29 51 64  4 77 14 76 73  3 19 32 28 22 12 19 69 58 36 23 20 21 60 67 65 70 54  4 48 78 73 68  9 11  9 50  2 52 78  0 62 75 54 69  8 23 51 60 41 80  8 45 14 20 22 50 61 62 80 21 34 73 54 18  4 
+78 39 56 10 43 77 65 61 23 59  5 67 46 21 39 73  9  5 74 60 71 11 20 25 72 19 17  9 67 79 58 74 68 55 65 55 73  2 68 51 46 28 54 62 75 23 54 60 71 53  6 28 50 19 25 19  7 39 15 55 54 36  1 52 50 60  1 29 59 31 19 13 34 80 62  0 48 56 30 66 70 35 30  1 52 22  5 20 44 48 65 56 78 20 79 21 52 23 36 36 
+54  6 48 25  2 75 35  4  8 64 34 51 38 37 10 74 64 10 24 52 71 44 20 42 72 53 65 79 24 17 45 71  2 29 47 80 28 17 68 70 72 77 74 42 75 64 63 75 37 37 75 56 55 10 40 20 72  4 31 65 77 27 60 42  7 61 30 33 51  2  9 60 78 10 75 48  0 77 15 76 77 31 63 27 45 70 74 64 11 39 25 65 43 80 48 33 75 52 17 53 
+17 76 68 30  9 33 29 13 57 68 29 43 25 54 17 76 51 34 24 48 25 70 49 69 68 24 76 75 30 61 24  2 17 64 63 69 60 16 40 71  1 70 45 32  5 77 40 13 47  8 63 74 25 41 43 34 22 46 17  5 11 55 78 17 75 58 13 49 25 25 57 11 77 36 54 56 77  0 68 60 59 73 22 63 22 51 26 79 19 62 63 19 47 72 47 15 38 11 46 39 
+76 18 31 26  7 22 62  9 40 68 38 45 21 64 72 56 35 60 75 14 11 33  4 13 24 17 64 40 30 78 72 15 39 18  6 80 18 16 63 79 48 21 10 20 75 62 56 64 25 75 20 56 58 58 58 42 45 45 59 44 31 28 77 50  9 31 78 38 56 54 46 21 24 54 69 30 15 68  0 11 10 35 20  3 46 70  3  6 80 60 22 46 12 25 17 79 58  2 75 22 
+44 34 74 42 48 30 73 26 58 37 34 66 72 53 41 35  4 15 56 43 28 34 41 35 65 49 60 60 73  3 55 46 25 32 27  1  8 17 45 79 22 30 10  8 25 15 73 31 12 69 45 69 32 59 65 16 48 52 23 51  2 12 69 61 28 30 19  5 32  5  6 22 14 39  8 66 76 60 11  0 73 32 28  4 46 74  4  3 42  2 75 80 62 71  7 27 28 49 62 27 
+19 46 33 21 40  9 28 67 76 16 49 28 30 54 24  8 37 14 40 18  8 23 34 60  9 11 68 67 51 61 39 41 32 26  1 23 46 49 44 54 40 17 21 51  6 72 46 28 62 40  5 69 38 43 20 61 64 74 51 11 25 23 56 45 78 72 20 24 49 40  5  3 18 74 23 70 77 59 10 73  0 60 67 39 22 37 38 32  2 76 34 67 80 44 53  1 42 48 60 46 
+30 62 42 66 24 76 35  1 46 73 75 13 42  7 41 31 34 57 13 17 37 24  9  5 77 73 22 63 75 29 62 66 18 75 35 24 60 69 46 78 55 63 60  5  7 71 18 47 71  7 71 61 37 68 60  5 15  7 73 25 41 70 32 38 63 45 36  7 42 37  7 41 18 23 51 35 31 73 35 32 60  0 29 73 73 53 22 40 32 45 32 63  1 71 13 15 52 26 68  8 
+ 3  9 77 19 38 25 52 68 35 29 59  5 50 50 23 40 41 46 49 26 48 35 28 64 17 62  4 70 43  7 78  7 72 33 11 61 52 72 53 32 64 39 51 77 63 59 10  6 60 28 17 53 50 59 34 62 29 24 24 76 53 43 64 24 80  2 43  6 62 31 76  3 55  2 60 30 63 22 20 28 67 29  0  8 32 60 15 21 35  4 45 51 68 25 45 29 18 70 45 69 
+56 29 13 57 17 22  7 24 78 40 22  8  3 34 62 41 20 21 16 31 11 26 71 43 28  7 13 24  7 12 25 11 15 30 20 71 61 15 58 71 41 64 22 72 56 74  6 14 61 31 50 46 50 35 61 62 75 36 75 51 39 79 39  4 46 51 32  4 52 47  4  7 22 77 41  1 27 63  3  4 39 73  8  0  2 27 13 68 47  7  7 20 16 12 55 28  8 72 75 48 
+36 20  4 78  8 33 63 49 44 36 49 11 44 73 63 47 78 69 79 61 52 68 35 26 11 59 42 20 25 52 33 11 20 60 40 20 45 55 23 80 51 34 18 58 35  8 61 69 54 77 46 67 40 18  1 39 23 46 23 22 28 68 40 12 53 64 25 67  1 38 19 17 27 37 80 52 45 22 46 46 22 73 32  2  0 33  3 15 64 25 38 51  4 14 79 79 39 26 59 26 
+42 60 39 43 57 16 45 40  8 52  8 26 29 67 25  4 23 40 23 33  7 30 57  7 71  8 14 30 37 39 38 15 78 47 52 13 42 33 71 61 57 80 13  1  6 63 28 26 38  7 63 28 51 32 70  8  1 30  7 72 27  2 64 52 60  6 17 17 61 32 11 53 79  8  8 22 70 51 70 74 37 53 60 27 33  0 61 67 42 78 34 66 62 72 56 59  1  3 38 69 
+75 62 78 79 22  9 15 69 62 33 39 24 13 20 10 56  3 33  4 12 80 76  8 55 14  5 19 61 33 24 62  5 69  4 67 61 42 61 66 77 18 79  6 21 30 30 29 25 42 34 66 56 35  4 16 41 61 21 21 68 74 51  9 14 70  2 39 68  4 14 21 75 42 62 45  5 74 26  3  4 38 22 15 13  3 61  0 41 24 55 27 35 79 37 33 12 19 47 68 70 
+ 9 12 39 10 59 39  9 66 48 57  4 79 16 25 28  3 61 48 59 69 30  5 11 57 65 39 25 45 79 50 15 35  2 26 17 18 77 68 36 60 71  4 37 44 59 52 44 31 34 77 66 80 13 59 31 75 43 13 65 75 32 13 36 71 76 54 62 62 24 17 73  5 43 23 14 20 64 79  6  3 32 40 21 68 15 67 41  0 61 32 30 53 26 65 40 51 52 61 30 65 
+61 16 64  6 19 55  4 61 35 32 67 55 71 33 44 44 51 72 54 27 69  2 27 50 74 38 78 79 30 20 32 53 54 46  5 69 39 67 32 32 42 49 79 23 24 38 61 65 64 37 68 14 73 48 78  8 65 51 56 68 44 41 59 17 58 49 66 37 47 33 34 61 35 48 20 44 11 19 80 42  2 32 35 47 64 42 24 61  0 56 38 16 39 66 40 18 10 36 66 62 
+61 49 15 32 71 44 16 69 62 18 41  6 35 67 66 65 61 65 35 40 53 65 78 10 77 27 48 48  5 54 21 35 76 48  2 10  3 77 40 31 22 46  1 73 77  4  1 69 51 28 42 35 72 32 55 38 34 25 79 58 78 57 41 61 76 58 77 32 29 20 56 27 64 30 22 48 39 62 60  2 76 45  4  7 25 78 55 32 56  0 19 24 53 12  8 40 29  3 77 38 
+65 68 22 57 11  1 57 70 31 51 77 38 29 50 50 23 68 10 30 61 18 61  6 43 40 11 40 47 19 18 19 24 35 10  3  4 37 76 35 57 61 38 50 35 11  1 26  2 21 76 34 71 50 17  5 68 52 43 69 29 32 32 35 44 63 71 62 62 38 51 70 49 19 72 50 65 25 63 22 75 34 32 45  7 38 34 27 30 38 19  0  9 34  6 16 35  6  2 71 78 
+57 46 54 46 74 46 78 77 78 44 14 52 17  5 58 51 24  7 80 41 74 46 24 38 18 79  4 59 20  7 18 30 53  2 16 62 24 22 24 63 30 69 70 39 52 36 67 49 21 39 73 71 61 24 38 72 80  9 39 57 64 15 73 75 51 65 50 29 77 27 15 26 59 69 61 56 65 19 46 80 67 63 51 20 51 66 35 53 16 24  9  0 42 59 22 67 79 70 39 66 
+44 58 44 12 61 79 50 44 58 34 35 52 42 72 17 69 57 42 63 39  9 74 66 64 39 26 31 62 69 36 46 34 78 48 52 28 20 23 55 10 73 51 37 78 44 79 44 42 73 64 57 59 57 56  3 31 71 60  6 29 37 54 76 67 68 79 74 55 25  8 43 65 12 78 62 78 43 47 12 62 80  1 68 16  4 62 79 26 39 53 34 42  0 54  9 78 40 67 52 57 
+25 45 15 74 38  7 22 61 47 15 35 58 37 22 70 44 77  5 49 49 52 63 38 45 19 36 18 46 69 57 19 17  1 72 36 44 40  6 41 78 38  1 37  2 25 60 19 32 75 58 54 17 55 69 67 66  6 26 76 73 35 72 48 54 65 42 76 29 19 47 27 43 17 15 80 20 80 72 25 71 44 71 25 12 14 72 37 65 66 12  6 59 54  0 12 14 38  5 49 59 
+47 26 67 76 35 42 26 18  3 21 47 20 59 38 78 63 30 45 28 37 76  3 43 15  6 43  2 25 38 76 24 48 28  3 27 47 38 15 77 80  7 37 12 57 35 46 71  7 74 36 53 69 25 44 26 34 65 70 38 37 53  9 29 76 35 71 12 16 18 36 37 23  6 52 21 79 48 47 17  7 53 13 45 55 79 56 33 40 40  8 16 22  9 12  0 57 42 58 24 74 
+55 62 31 55  2 28 13 26  9 38 54 15  9 28 46  8 21 78 22 47 61  3 76 71 31 32 42 62 74 16 68 42 14 74 66  1 49 59 64 12 76  2 63 78 41 32 67 19 33 33 20 76 80 37 11 35 43 42 40 79 39 26 14 50 17 42 46 77  7 36 64 55 67  9 34 21 33 15 79 27  1 15 29 28 79 59 12 51 18 40 35 67 78 14 57  0 70 69 25 21 
+26 67 59 21 41  6 37 46 62  8 20 61 31 77 50 23 56 76 69  3 69 24 68 30 27 20 25 47 60 33 73 75  9 32 56 46 40 61  9 61 12 24  7 40 64 34 26 16 16 78 57 15 41 46 44 79 37 21 78 12 66 80 68  9 48 29 50 50 71  4 79 70 40 15 73 52 75 38 58 28 42 52 18  8 39  1 19 52 10 29  6 79 40 38 42 70  0 80 39 23 
+75 67 38 16 30 13 15 60 30 78 60 58 73 36 13 17 61  6 15  8 52 16 68 23 69  3 26 77 77 36 65 26 39 44 62 35 19 58 62 44  7 42 63 58 62 63 37 64 14 60 30 73 18 54 13 11  2 24 17 25 29 40 28 31 15 64 34 36 17 41 79 61  3 48 54 23 52 11  2 49 48 26 70 72 26  3 47 61 36  3  2 70 67  5 58 69 80  0 37 47 
+50  7 28 15 49  8 80 50 38 76 45 51 52 15 64 51 61  5 16 72 13 73 23 27 70  2 61 75 17 69 70 70 76 53 42 33 64 12 72 64 38 48 15 33 12 46 60 46 38 55  1 46 32 54 51 70 13 16 62 60 16  3 72 21 36 71 41 11 53 64 61 12 66 72 18 36 17 46 75 62 60 68 45 75 59 38 68 30 66 77 71 39 52 49 24 25 39 37  0  5 
+22 68 21  3 15 38 80 73  7 47 16 72 51 46 22 47  4  9 10 58 66 38 46 74 23 31 75 32 73 16 29 25 53 38 50 72 32 62 79 62 18  8 71 79  2 80 64 33 64 65  3 19 20 34 10 36 80 47 21 69 22 75 34 61 27 65 17 13 10 27 38 18 37 20  4 36 53 39 22 27 46  8 69 48 26 69 70 65 62 38 78 66 57 59 74 21 23 47  5  0 
+
+ 0 25 20 23 18 30 21 19 23 21 20 15  5 12  2 16 13 26 13  6 23  1  6 17 11  8  1 26  5 10 16 27  3 18 18  3  3  9 24 26 26 11  5 16  9 26  7 27 20  1  5 10 21 15 24 18  7  8 17 18 24 30 24 20 12 16 13  5 24 11 29 23 10 19  2  6  4 26 22  2 16 30 17 23 20 29 28  2 15 23 16  1 16 30  5 19 20 13 18 23 
+25  0  1 23 13 13  8  9 30 19 19 10 20 17 30 23 30 18 29 15 12  1  6  5  8 20 25  2 10  5 18 28 28  3 20  6 18  9  7 23 11 24  6 12 24 22  7  6 18 30 16  1 17  1 30 11  5 11  3 15 12 12 25 25 15 27  3  4 21 19  4  2 27  2  8 23  9 26 16 10 11 15 19  7  9 23 28 24 30 20 23 26  3  5 28 29  9 10 25 14 
+20  1  0 15 23 18  9 29 19  5  5 22 12 17  2  6 15 24 25  6 16  3 16 24 27 27 16 17 16  2 21 14 25 11 18  4 24 19  5 18 14 12 16 17  5 30 25 26  6  3 26 19 11 19 18  4 17 11  9 23  6  2 19  5 28 27 16 25  4 20  2  5 27 28 22 12 15 29  4 13  2 11  6 10 27 21  7 24 19 25 10 27 24 29 26 24 27 19 30  9 
+23 23 15  0  8  9 21 21 22 25 10  9 17 26 16 28 15 26 17 19  3 20 17 20 16  7 26 19 18 30 22  1 12  8 20 10 27 21 22 21 10 18  6 30 17 12  2  1  2 26 24 22 18 25 28 29 16  8  9 24 23 24  6 13 23 11 20 16  8 29 17  1  4 27 30 25 29 30 16 13  3 30  7 15 27 29 23 17  9  5 18 12  1 20 21  3 13 21 12 19 
+18 13 23  8  0  1  9 11  9 28 21  6 19  2 27  8 30 20  8 15 18 25 23 23 18  1 13 13  8 10 23 15 21  4  3 20 10 14  5 30  6  4  3 19 16 13 19 28 27 17 21  5 12 13 16 20 11  3  8  1  1 24 13 29 14 23  2 11 11 12 12  2 13 20 14  9 25 22  5 16 25 18  6  4 19  3 28 15  6 22 22 12 12 15 22 13 10 10 28 14 
+30 13 18  9  1  0  4  1  9  4 15 17  1 14 15 10 30  4 24  7 29 14 29 29 30 24 26 19 14  9  6 14 26 12  4 12 15 14  6 27 27 27  2 16 17  7  9 13  7 20 17  7 26 19  2 29  5  8 11 26 21 23  3  7 16  2 11  7 27 17 12 12  3 30 21  5  5 26 16 11 27  5 27 16 16  4 12 22 23 20  9 10 25 14  1  9 19  2 17  1 
+21  8  9 21  9  4  0  4 10  8 11 22 11 15 15  4 28  7  8 30 10  2  1 19 17 19  3 23 25  8 18 19 16 28 17 23 10 19 16  3 24 10 26 23 19 21 19 27 16 22  5 30  2 10 12 25 21 16 27 17 10 22 21  1  4  5  8 26 23  2 13  3 28 13  1 23  1 12 28 16 17 28 19 13  5 20 10 28 20 12 20  8 26 15 28 27 23 13 13  1 
+19  9 29 21 11  1  4  0  9 30 30  3 29  3 22 28 22  6 28  2  7 18 16 11 17 12 17 21 14 24 25 24 28 21 24 26 27 28 19  3 24 10 24  3  8  3 22 15  5 26 28 30  7 10  3  7 10  8  7  2 23  8 29 19  2 12 11 17 13 29  5  5 26  2 13 16 30 14 22 28 19 26 19 22 12 16 10 28 21  9  3  7 17 18  3  7 30 29 11 14 
+23 30 19 22  9  9 10  9  0 23 13 20 30  3 17  1 15 30 19 21 24 15 16 25 20  8 27 12  5 16 17 29 22 11 10  8 19 11  9 11  3  4 25 12 30  1 29 14 23  5 12 28  6 27 11 15 23  1  6 11  3 25 12 10  3 14  6 26 26 17 27 10  1 15 29  9 30 12 28 17 16 21 11 29  5 11  7 21 11 30 30  7  2 10 22 22 23 16 26  5 
+21 19  5 25 28  4  8 30 23  0 14 14 20 21  7  3 27 11 30 26 17 22  8 26  2 13 15 26  3  1 25 14  7 27 13  4  4 26 19  4  4  9 21 17 19 12 14 19  8 27 13 19 15  7 22  9  5  1  6 15 20  1 24 29 21 23  7 25  3  2 17  1 28 29 29  7 23 28 19  5 17 27 22 19 15 15 14 23 10 23 25 11  4 29  1 10 17 12 13  6 
+20 19  5 10 21 15 11 30 13 14  0 12 20  2 18 13 27 22 20  6 17 24  9 19  8 24 30 21 29  1 17 30  4  5 27 17  3 30  4 17 18  3 23  3 15 23  8 11 19 30  4 29 20 17 18 16 10 27 26  3  7  1  2 14  7 29 12  7  6 23  7  4  7 17  1 28 23 23 23  7 21  4  1 15 15 11  6 15  5 30 23 26 11  8 20 20 23 23 21  4 
+15 10 22  9  6 17 22  3 20 14 12  0 18 25 15 22 14 10 11 27  2  8 19  3 22 16  7 28 10  6 15  6 11  6 17  3 28 15 27 21  6 17 15 29 19  3 10  5 22 30 16 11  4 27 25 12 29 29 30 21 19 12 29 12 18 18 13 17  9 27 27  3 30 28 20 26 22 20 30 18  1 10 27 28 14 25 15  5 11  6 21 24  4 27 27 30 27 27  9  6 
+ 5 20 12 17 19  1 11 29 30 20 20 18  0 16 30 29 20  4 13 11 24 29 11  7 28 26 16 19  6 27 28 23 13 21 11 10 27 23 20 17 17 20  5 29 20 12 23 12 15 24 13 16 17 23  5 23 25  8  7 23  7 17 13 23 13 10 23 25  3  1  7 17  1 28 20  4 18 13 14 21 19  8 30 17  6 18  8 15 27 24  3 25 29 27  6 18  2 18  8  5 
+12 17 17 26  2 14 15  3  3 21  2 25 16  0 22  9 12 25 12  7 24 26 18  3 14 11 13 25 26 27 18  7 15  8  2  2  4 22 25  1 16  7 10 13 12 20 28  8 22  8 15  9 21 24 21  3 30 29 29 20 23 21 18 20 17 26  3 12 28 28 26 22 12 23 26 29 23 16  8 27 13 19 21  8 19 19 25 13 12 28 28 10 21 28 16 23  5  2 27  6 
+ 2 30  2 16 27 15 15 22 17  7 18 15 30 22  0  5 15 19 26 22  1 20 10  8 22 28  9 16 25 11  6 24  1 27 17  8 16 15 26  3  8 27 17 27 14 26 29 10 17  1 23 28 29 26 14 30 30 16 10 11 24 26 23 11 19  1  9 22 22 17 13  8  2  1  8 29 16 18  4  3 30  7 23 23 11  8 28  7 24 27 26 17 25 22  1  4 26 10 14 20 
+16 23  6 28  8 10  4 28  1  3 13 22 29  9  5  0 22 14  9 28  8  3  4  6  9 29 26 17 17 18 27 17 11 29 22 20  1 24 16 26 17 23 16 14  8 29 22  5 21 30  6  3 16 28 11 29 14 30 23  2 17  4  2 19 19  2 27  5 22 27 25 23 10 13 21 23 28  6 11  8  8 11  3 24 28  2  4 28 27 12 15 26  3 17 27 11  2  1  6 18 
+13 30 15 15 30 30 28 22 15 27 27 14 20 12 15 22  0  4 15 22 13 18 25  4 12  5  3 15 24 27  9 12 23 19 10  5  7  4 25 13  4  9 15  4 15  4 22 26  3 13 28 20 19  1 18  1 24 28 16 10  5  7 16 17  2 21 18 13 13 10 29 21  6 15 24 18 21 16  3 28 25 17  5  1  4  9 29  2 30 10 22 19  2 16  9 12 22 28 15  1 
+26 18 24 26 20  4  7  6 30 11 22 10  4 25 19 14  4  0  8  9 10  8 23  7 18 13 15 16  8 30 29 20 25 17  3 29 11 24  2  3 28  5  3 18 18  7 12 11  3 17 21  7 21  2 19 26  7  1  9 25 16 22 28  9 15 12  8 30 19 18 16 21 27  5 23  8 11 10 15  5 21 20  1 24  3  7  1 28 20 26 30 22  1 12 21  8 15 26 23 23 
+13 29 25 17  8 24  8 28 19 30 20 11 13 12 26  9 15  8  0 23 21  6 14 15  3  3 13  1 23 22 13 11 20 27 13 12 27  3 18  3 29 10  3  7 26 13 13 30 18 27 16 24 12  4 29 22 24  4  7 12 25  7  2  5  3  1  4 30 25  1 23 15  7 21 21 20 14  5 29  9  1 26  9  8 19 19  6  9 25 27  3 29 29 11 28  3 11 13 28  9 
+ 6 15  6 19 15  7 30  2 21 26  6 27 11  7 22 28 22  9 23  0  9  1  5 21  1  1 26 16 18 17 21  4 28 10 24 14  6 18 12 29 23 10 28 19  1  8  5  2  9  8 27 24 14 16 24 26 21 14 21  1 27 13 21 26 24 20  4 14 18 30 27 13 11 24 17 19  6  1 30  2 18 22 10  4  8  2  5 23 16 21 19 17 23 22  4 16  7 20 17 28 
+23 12 16  3 18 29 10  7 24 17 17  2 24 24  1  8 13 10 21  9  0 20 24  8  8 10  7 14  3  5  4  6 11 26 22 20 12 25  7 28 15 24  3  1  9 25 10 23  9  9  9 15 25 13 25 13 29 21 30 26 20 17  1  8 23 26  8 21 19 19 19 29 13 21 12 13 21  1 29  3 17 24  7 16 30 26 19 22  2 13 22 15 19 20 30  4 29 16 18 30 
+ 1  1  3 20 25 14  2 18 15 22 24  8 29 26 20  3 18  8  6  1 20  0 27 19 30 18 22 23  2  2 25  3 30 21  8  7 14 13 20  6 21 16 17  7 16 12 23 27  8 14 25 23 24  7 28  1 23  6 26 27  4  2 29 20 18 29 16 17 27 17  6  9 14  8  8 27  7 23  6  9 27 26 13 25 24 21  6 20 19 30 27 18  7 19  7 30  6 18  5 10 
+ 6  6 16 17 23 29  1 16 16  8  9 19 11 18 10  4 25 23 14  5 24 27  0  1 22 28 18 14 16 13 24 21  8  2 30 14 29 30 27 19 11 30 12  3 22 15 17  1 13 27 23 26 16  8  4 14  5 15 26  7  1 28 14 25 29 26 28  1  7 27  9 16 24 30 16 26 21  4  5 14  5 13 20 26 30  9 18 24 10  3 29 20 17  3  6 13 28 26 15  5 
+17  5 24 20 23 29 19 11 25 26 19  3  7  3  8  6  4  7 15 21  8 19  1  0  6 27 14  8 27 11 20 14 12 29  8 27 14 13 19 29 14 17 13  7 14 30 16  4 26  3 13  1 14 20 12 25  1 18 18 26 13  5 12 19 13  6 10  3 25 30 16 21 17 16 25 29  4  6 25 17 12  8 24 23 18 25 17 13 11 10  3 19 19  7  2 26  2 17 26 10 
+11  8 27 16 18 30 17 17 20  2  8 22 28 14 22  9 12 18  3  1  8 30 22  6  0  1  5 12 22  9 22  2  5 23 30  1 26 12 14 20  5 26 20 25 30 25 19 27 20 30 28 14  9 24 22  9 10 27  2 23 28  8 29 27  1 25 13  6 27 11  4 13  4 24 30  9  7 19 30 15 16 13 15 22 22 24  7 14 27 20 25 30  3  5 25  7 29  8 14 26 
+ 8 20 27  7  1 24 19 12  8 13 24 16 26 11 28 29  5 13  3  1 10 18 28 27  1  0 23 25 12 21  7  9 12 12 12 18 19 11 10 27 29 14 25 29 23 14  4  9  8 21 12 16  6  2 19  3 28 27 19 17 28 22 17 27  5 25 23 18 28 12 27 23 11 22  7 26 27 26 10 12 27 12 29 28 17 20 11 16 11 18 30 11 16 21 25  5  8 21 21 10 
+ 1 25 16 26 13 26  3 17 27 15 30  7 16 13  9 26  3 15 13 26  7 22 18 14  5 23  0  3  2 28 20  6 16 13 11 25 24 13 21  2 20 27 16 30 20 17  2 21  9 21 28  4  5 27  4 11  3 22  3 28  3 27 21  2 22  7 29 19 17  1  3 11 26  7 18  7 19 17  4 22  5  2  4  2 30 11  9  7 12  6  2 21  6 18 22  6  6 29  7  6 
+26  2 17 19 13 19 23 21 12 26 21 28 19 25 16 17 15 16  1 16 14 23 14  8 12 25  3  0  7 23 18  4 18  2  3 19 13 28  4 29 11 15 25  8 26 20 12 25 16  5  9 20 16 29  2 19 14  6  6 15 12 10 20 23  4 26 16  5 17 26 16 24  8  5 26 11 13  5 13 21  7 28 21  9 14 20 30  3 28 21 15 13 17 22 21 29 28 11  2  3 
+ 5 10 16 18  8 14 25 14  5  3 29 10  6 26 25 17 24  8 23 18  3  2 16 27 22 12  2  7  0  1 15 13 10  2 23 14 27 21 25 12  5 19  1  9  3 15 19  7  9  8 22 26  3 12  1 18  2 26 17  5 30 11 25 13 16 11 18 15  5 25 21  3 12  5 30 24  6 27  6 17 16  4  6  6 25  8 10 18 12  2 14 17 10 27 20 26 17  9 27 15 
+10  5  2 30 10  9  8 24 16  1  1  6 27 27 11 18 27 30 22 17  5  2 13 11  9 21 28 23  1  0 30  2 10 20 16 28 13 30 20 20 18 13  7 27  5  5 18  2  7  8  2 26  4 18 21 25 29 24  5 12  7 19 20 25 14 24 10 17  1 27  9 25  7 25 22  4 29 14 28 16 30 20  6  9 10  5 26 30 23 27  1  8 14  6  1  6 25 25 21 27 
+16 18 21 22 23  6 18 25 17 25 17 15 28 18  6 27  9 29 13 21  4 25 24 20 22  7 20 18 15 30  0  1 19 17 10 18 20  7 22 23 29  4 24 27 11  6 15 25 26 27 26 28 14 15 23 21  4 11 19 13  2  5  3 19  7 30 11 13  5 11 16  9  4 20 25  5 14  5 25 28 10 26 28  7  4 10  4 13 28 14 26 26  1 23 25 24  9  3 25 16 
+27 28 14  1 15 14 19 24 29 14 30  6 23  7 24 17 12 20 11  4  6  3 21 14  2  9  6  4 13  2  1  0 14  7 13 29 11 24 17 17  2 27 24  3 28 29 15 29 11 14 13 23 26  8  5 12  5 26 22  2  9 14 17 20 16  5  6 13  6 21 19 18 22 27 12 28 16 29  7 20 22 17  6 10 27 17 27 17 27 26 28 18  7  6 23 10 15 18 20 15 
+ 3 28 25 12 21 26 16 28 22  7  4 11 13 15  1 11 23 25 20 28 11 30  8 12  5 12 16 18 10 10 19 14  0 17 12  5  4  7 26  8 20  3 11 21 18  8 16 21 16 13 26 23  8 30 20 12  2 25 22 24 13  2  2 14  2 15  5  5 28 29 15 10  2 20 15 28 29 22 19 16 20 17 18  4 22 19  7 10 17 20  6 21 30 19 20  8 24  7 16  7 
+18  3 11  8  4 12 28 21 11 27  5  6 21  8 27 29 19 17 27 10 26 21  2 29 23 12 13  2  2 20 17  7 17  0  2 22  4 30  3  4 28  5 28  2 28  5  6 26 23 13 14 12 28  6  9 11 24 15 11  7 10 28  7 18 24  9 30 29 11 23 16 26 30 16 10 30 25  7  5 15 13 20 30  1 14 15  8  3 27 15  2 16 11 27  6 15 30  8 19 15 
+18 20 18 20  3  4 17 24 10 13 27 17 11  2 17 22 10  3 13 24 22  8 30  8 30 12 11  3 23 16 10 13 12  2  0  1 10 18  2 12 29 20 12 10 24  9  3 22 15  4  8  3  4 23 22 16 24 29 14 22  2 23 14 23 23  6  4 30  1  5 17 12  5 15 20 16 14 26 24 28  5  2  8 11  1 21  7 25 25  9 24  5  4 13  7 23 11 29 19  5 
+ 3  6  4 10 20 12 23 26  8  4 17  3 10  2  8 20  5 29 12 14 20  7 14 27  1 18 25 19 14 28 18 29  5 22  1  0 24 22  3 14 14  3 16  8 30  8  1  5 19  5  1  2 20  2 27  2  5  9 17 11 10 22  6  5 22  3 26 15  6 18 14 30  4  9 18  4  5  4 17 13 13 25 23  4 23 21  3 12  1  5 25 29  5 27  1 19 14  2  9 27 
+ 3 18 24 27 10 15 10 27 19  4  3 28 27  4 16  1  7 11 27  6 12 14 29 14 26 19 24 13 27 13 20 11  4  4 10 24  0 29  4  1 22 20 10 30  9  7 17 24  1 20 17  2 10 16  9  8 15 24 18  2 26 17 14  2 17 28 22  7 14 25 18 18 25 26 18 19 20  5 11 13 30 26 25 26  3 27 25 25 12 16  2 15 28 15 10  6 28  2 15 12 
+ 9  9 19 21 14 14 19 28 11 26 30 15 23 22 15 24  4 24  3 18 25 13 30 13 12 11 13 28 21 30  7 24  7 30 18 22 29  0 30  3  3 21 21  2 14 23 28  5 18 15  9 22 29 16 25  7 11 23 23  1 12 11  1  7 30  2 10 29  1  9 21  3  8 18 25 24 11 24 20 15 22 24 23 18  4  8 19  8  1 27 22  5  9 13 25  8 21 23 21  3 
+24  7  5 22  5  6 16 19  9 19  4 27 20 25 26 16 25  2 18 12  7 20 27 19 14 10 21  4 25 20 22 17 26  3  2  3  4 30  0 26  1 12  1 18 23 14  2 16 14  7 21 30 16 14  3 11 24 12 12 21 25 14 18 12 10  2 29 15  1 10 13 23 29 29 28 18 28  6 10 26 16 21 27 13  5 28 19 18  5 30 22  4 29 25 16 20 25  5  5  6 
+26 23 18 21 30 27  3  3 11  4 17 21 17  1  3 26 13  3  3 29 28  6 19 29 20 27  2 29 12 20 23 17  8  4 12 14  1  3 26  0  5 16  6 28  1 19 30  9  2 17 24  4  9 28 20  7 14 30  6 22 24  9  3 13  3 14  7  8 15  7  3  2  8 23  2 14 13  5 15 19 30  5  9 15 10 29 18 27 17 16 28 30 25 17 18  7 18 14 16 13 
+26 11 14 10  6 27 24 24  3  4 18  6 17 16  8 17  4 28 29 23 15 21 11 14  5 29 20 11  5 18 29  2 20 28 29 14 22  3  1  5  0  9 19 15 11 13 26 27  5 22 12  4  2 20 21 17 11 12 26 11 28 18  7 29 18 27 19  6  2 28  5 15 24  5 22 25 24  4 11 15 30 29 23 12 10 13 13 27  3 13 10 24 20 29  5 24 29 18  9  7 
+11 24 12 18  4 27 10 10  4  9  3 17 20  7 27 23  9  5 10 10 24 16 30 17 26 14 27 15 19 13  4 27  3  5 20  3 20 21 12 16  9  0  4 12  6  1 24 11 13 18 20 20 15  7 14  2 24  8 25  1  1  8 13  5 30 26 28 14 16  6 19  5 25 27 23 30 30 10  8  9  6 14 25 10 21 30 12  5 23  9 18 15  9 14  1 26 18 26  5 29 
+ 5  6 16  6  3  2 26 24 25 21 23 15  5 10 17 16 15  3  3 28  3 17 12 13 20 25 16 25  1  7 24 24 11 28 12 16 10 21  1  6 19  4  0 14  5 25  7  5 22 30 30 10 19  7 19 29 14  3 27 28 15  8 11 23 22 26  1 29 23 21  7 30 28 19 12 13 16 15 21  6 22 12 22  6 14 12 19 23 17  8 12 22  3 10 22 18 19 13 30 17 
+16 12 17 30 19 16 23  3 12 17  3 29 29 13 27 14  4 18  7 19  1  7  3  7 25 29 30  8  9 27 27  3 21  2 10  8 30  2 18 28 15 12 14  0 22 25 20 15 22 14 13 13 24 24  8  6 25 22 12 29 17 18  2 26 18 27 24 21 28 25  8 22 10 23  3  3  3 12 22 24 17  5  2 17 27 13 27  6  5  4  9 21 27  1 15 27 29 28 10  7 
+ 9 24  5 17 16 17 19  8 30 19 15 19 20 12 14  8 15 18 26  1  9 16 22 14 30 23 20 26  3  5 11 28 18 28 24 30  9 14 23  1 11  6  5 22  0 21 15 26  7  9 17 21 23 20 24 23 23 29 17 28 21 15 11 12  4 21 24 23 24 28  7 18  5  2 16 11 18 25  4  5 21 23 16  9  6  3  6 28 25 15 17 13 26 14  7 29 28 11 15 19 
+26 22 30 12 13  7 21  3  1 12 23  3 12 20 26 29  4  7 13  8 25 12 15 30 25 14 17 20 15  5  6 29  8  5  9  8  7 23 14 19 13  1 25 25 21  0 25 17 10  9 26 16 16 23 13 20  5 23  5  7  8 11  5 25 21 27 26 12 26 27 24 26 14 12 10  3  2 24  4 17 15 17 25 13 19 17 11  7  6 21 15  6 19 14 21 17 25  3 17 10 
+ 7  7 25  2 19  9 19 22 29 14  8 10 23 28 29 22 22 12 13  5 10 23 17 16 19  4  2 12 19 18 15 15 16  6  3  1 17 28  2 30 26 24  7 20 15 25  0 14 13  2 17 29 21 19 22 19 17  8 21 10 16 27  8 26 27 25  1 29 22 12 17 24  6 22 29 14  6 26 24 15 18 26  2 27 16 17  1 20  6  8  2 14 11  7 17  2 29 19  3 20 
+27  6 26  1 28 13 27 15 14 19 11  5 12  8 10  5 26 11 30  2 23 27  1  4 27  9 21 25  7  2 25 29 21 26 22  5 24  5 16  9 27 11  5 15 26 17 14  0  6 12  1 28 26  5 28 10 17 19 11 26 26  2  8 21 14 21 16 17  9 29 29  4  3 14 12 10  4  1 16 13  6  1  6 20  8  2 28 18 23 19 23  4  9 23 25 14  3  8 18 24 
+20 18  6  2 27  7 16  5 23  8 19 22 15 22 17 21  3  3 18  9  9  8 13 26 20  8  9 16  9  7 26 11 16 23 15 19  1 18 14  2  5 13 22 22  7 10 13  6  0  9 29 24 24 28  5 11  5  3  5 30  8 27  9  1 19  5  8 19 25 23 13 17 26 25  8 24  2 26 29 24  1  6 10 24  6 11 27 23  6 29  5 12 19  6  6 16  6  5 26 23 
+ 1 30  3 26 17 20 22 26  5 27 30 30 24  8  1 30 13 17 27  8  9 14 27  3 30 21 21  5  8  8 27 14 13 13  4  5 20 15  7 17 22 18 30 14  9  9  2 12  9  0  6 24  8 21 30  6 14 26 12 18 29  8 26 13 13 20 23 18  3 18 18 15 14 29 15  7 15  2  7 28 22 30  7 12 29 18  7 11  2  8  6  7 20 13 23 27 10 19  3  7 
+ 5 16 26 24 21 17  5 28 12 13  4 16 13 15 23  6 28 21 16 27  9 25 23 13 28 12 28  9 22  2 26 13 26 14  8  1 17  9 21 24 12 20 30 13 17 26 17  1 29  6  0  8 29 17 17 27 23 11  3 21 17 24 25  1 18 16 28 28  9 22  6 24  5 24 25 13  6  5 16 17 27  9  8 24 28 29  6 13 15 15 11  1  5 16 11  5 30 11 19 15 
+10  1 19 22  5  7 30 30 28 19 29 11 16  9 28  3 20  7 24 24 15 23 26  1 14 16  4 20 26 26 28 23 23 12  3  2  2 22 30  4  4 20 10 13 21 16 29 28 24 24  8  0  4 15 17 12 16 21 20 15  1 15  3  1 28  7 26 12 30 30 25 17 24  9 13 29  4  5  1  9  7 25 21 19 27 22 27  7 24  7 16 14  5  2  6 12 22 29 13 29 
+21 17 11 18 12 26  2  7  6 15 20  4 17 21 29 16 19 21 12 14 25 24 16 14  9  6  5 16  3  4 14 26  8 28  4 20 10 29 16  9  2 15 19 24 23 16 21 26 24  8 29  4  0 29 21  2 28 29  3  9  6 12 21  3  9  7 23  2 18 29  1 19 17 19 15 18  7 14 21  5 15  9 25  7 27  5 22  8 24  1 18 20  9 30  3  9  4 17  4 12 
+15  1 19 25 13 19 10 10 27  7 17 27 23 24 26 28  1  2  4 16 13  7  8 20 24  2 27 29 12 18 15  8 30  6 23  2 16 16 14 28 20  7  7 24 20 23 19  5 28 21 17 15 29  0 18 14  5 20 10 22 12 16  1  8 13  6 13 28 13 19 26 15 25  6 10 28 23  3 17 21 24 25 20  3 13  9 16 21 29 13 28 29 22 20 23 20 17 20  2 24 
+24 30 18 28 16  2 12  3 11 22 18 25  5 21 14 11 18 19 29 24 25 28  4 12 22 19  4  2  1 21 23  5 20  9 22 27  9 25  3 20 21 14 19  8 24 13 22 28  5 30 17 17 21 18  0  2 14 17  3 25 30  1 29 10 24  8 25 18 19 25 26  2 27  7 12 19 27 24 17 11 23 27 19 28  2 26  5 29 25 11  9 13  3 12 23 13 15 10 20 28 
+18 11  4 29 20 29 25  7 15  9 16 12 23  3 30 29  1 26 22 26 13  1 14 25  9  3 11 19 18 25 21 12 12 11 16  2  8  7 11  7 17  2 29  6 23 20 19 10 11  6 27 12  2 14  2  0 23 10 12  7  3  2 27  2 25  6  4 10 27 25 22  5 18 14  3 23 11  9 11  7  2 24  8 10 20  2 12  1 20 23 26  7  8 23  5 21 16 16 13  8 
+ 7  5 17 16 11  5 21 10 23  5 10 29 25 30 30 14 24  7 24 21 29 23  5  1 10 28  3 14  2 29  4  5  2 24 24  5 15 11 24 14 11 24 14 25 23  5 17 17  5 14 23 16 28  5 14 23  0 18 15 29  3 24  1 21 23 26 21  1  7 23  8  1  5 10 30 28  5 16  5 25 22 11 10  2 24  2  2 27 27 24 29 24 22 24 15 25 17  8 20  5 
+ 8 11 11  8  3  8 16  8  1  1 27 29  8 29 16 30 28  1  4 14 21  6 15 18 27 27 22  6 26 24 11 26 25 15 29  9 24 23 12 30 12  8  3 22 29 23  8 19  3 26 11 21 29 20 17 10 18  0  8 14 19 13  9  1  1 13  1 27 23  8  7  6 23  1 21 22 20  4  1 11 27 20 30 29  9 30 26 20 25  2  5 20 13 17  9  5 11  5 16  2 
+17  3  9  9  8 11 27  7  6  6 26 30  7 29 10 23 16  9  7 21 30 26 26 18  2 19  3  6 17  5 19 22 22 11 14 17 18 23 12  6 26 25 27 12 17  5 21 11  5 12  3 20  3 10  3 12 15  8  0 14 21  5 13 15  2 24  6 23 26 12 19 17 15 30 18 21 16  3  3 11  5 21 12  8 22 10 20  5 23 13 10  8 27 21 28  6 10  7 21 29 
+18 15 23 24  1 26 17  2 11 15  3 21 23 20 11  2 10 25 12  1 26 27  7 26 23 17 28 15  5 12 13  2 24  7 22 11  2  1 21 22 11  1 28 29 28  7 10 26 30 18 21 15  9 22 25  7 29 14 14  0  4  9 16 16 17 30  1 21 10 21 23 20 20 25 23 17 27 16 21 23  3 10 26 13 27 24  1 13 18  4 25 10 18 14 23 14 21  8  5 14 
+24 12  6 23  1 21 10 23  3 20  7 19  7 23 24 17  5 16 25 27 20  4  1 13 28 28  3 12 30  7  2  9 13 10  2 10 26 12 25 24 28  1 15 17 21  8 16 26  8 29 17  1  6 12 30  3  3 19 21  4  0 21 27  8 15 15 10 26 14  9  8 22 10  8 17 15  7  2 10 27  2 19 22 30  7  7 26 11 24  8  4  2  4  4 16  5 22 15 28 22 
+30 12  2 24 24 23 22  8 25  1  1 12 17 21 26  4  7 22  7 13 17  2 28  5  8 22 27 10 11 19  5 14  2 28 23 22 17 11 14  9 18  8  8 18 15 11 27  2 27  8 24 15 12 16  1  2 24 13  5  9 21  0 13 18 16  9 22 26 11  5  4 10  5 10 20  6 21  7 19 24 13 21 15 25  7  9 27  9 11  5 26  2 12 19 22  6  2 11 27 11 
+24 25 19  6 13  3 21 29 12 24  2 29 13 18 23  2 16 28  2 21  1 29 14 12 29 17 21 20 25 20  3 17  2  7 14  6 14  1 18  3  7 13 11  2 11  5  8  8  9 26 25  3 21  1 29 27  1  9 13 16 27 13  0  6 24 25 25 16 19  8 13  1  3  8 11 13 10  4 11  1 30 27 14 13 28  4 27 24 15 30 28 12 30 10  5  5 25 10 12  2 
+20 25  5 13 29  7  1 19 10 29 14 12 23 20 11 19 17  9  5 26  8 20 25 19 27 27  2 23 13 25 19 20 14 18 23  5  2  7 12 13 29  5 23 26 12 25 26 21  1 13  1  1  3  8 10  2 21  1 15 16  8 18  6  0 22 30 13  9  4 30 27 28 20 16 13 17 23 25 28 13 24 22 18  8  4  9 25 17 25 27  6 26  5 18  5 23 26 12 18 19 
+12 15 28 23 14 16  4  2  3 21  7 18 13 17 19 19  2 15  3 24 23 18 29 13  1  5 22  4 16 14  7 16  2 24 23 22 17 30 10  3 18 30 22 18  4 21 27 14 19 13 18 28  9 13 24 25 23  1  2 17 15 16 24 22  0  9  7 10 23 28  6 26 28 18  1 11 12 23  4 17  1 30 13  3 23 15 21  4  1 27  4 20 29  3 27 25  4  4 11 13 
+16 27 27 11 23  2  5 12 14 23 29 18 10 26  1  2 21 12  1 20 26 29 26  6 25 25  7 26 11 24 30  5 15  9  6  3 28  2  2 14 27 26 26 27 21 27 25 21  5 20 16  7  7  6  8  6 26 13 24 30 15  9 25 30  9  0  5 20  8 12 26 15 24 23 17 12 29 20 27  3 15 24 17  1 16 27  8  8 17 30  6  4 12  9 24 10 23  9  9 10 
+13  3 16 20  2 11  8 11  6  7 12 13 23  3  9 27 18  8  4  4  8 16 28 10 13 23 29 16 18 10 11  6  5 30  4 26 22 10 29  7 19 28  1 24 24 26  1 16  8 23 28 26 23 13 25  4 21  1  6  1 10 22 25 13  7  5  0 15 29 28  1 19 16 22 22  3 16  7 22 23  9 20  8 15 16 23 11  1 29 29 20 29 11  1  5  1 25  7 30 20 
+ 5  4 25 16 11  7 26 17 26 25  7 17 25 12 22  5 13 30 30 14 21 17  1  3  6 18 19  5 15 17 13 13  5 29 30 15  7 29 15  8  6 14 29 21 23 12 29 17 19 18 28 12  2 28 18 10  1 27 23 21 26 26 16  9 10 20 15  0 16 18 22 10 18 12 16  8  9  3 28  5  5  1 11 18  6  1  1  5  2  8 28 13 30 26 18 12  8  5  9 25 
+24 21  4  8 11 27 23 13 26  3  6  9  3 28 22 22 13 19 25 18 19 27  7 25 27 28 17 17  5  1  5  6 28 11  1  6 14  1  1 15  2 16 23 28 24 26 22  9 25  3  9 30 18 13 19 27  7 23 26 10 14 11 19  4 23  8 29 16  0 15 20 29 19 29 19  2  9  7  5  9 22  4 11 28 25 24 27 10 25 12 16 29  6  2 21 18 30  9  2 23 
+11 19 20 29 12 17  2 29 17  2 23 27  1 28 17 27 10 18  1 30 19 17 27 30 11 12  1 26 25 27 11 21 29 23  5 18 25  9 10  7 28  6 21 25 28 27 12 29 23 18 22 30 29 19 25 25 23  8 12 21  9  5  8 30 28 12 28 18 15  0 21 10 10 28 30 14 11  4 13 24 23 20 10 27  6 15  2 26  4 17 21 19  8 27  3 29 21 13  5 18 
+29  4  2 17 12 12 13  5 27 17  7 27  7 26 13 25 29 16 23 27 19  6  9 16  4 27  3 16 21  9 16 19 15 16 17 14 18 21 13  3  5 19  7  8  7 24 17 29 13 18  6 25  1 26 26 22  8  7 19 23  8  4 13 27  6 26  1 22 20 21  0  4 20 25 18  6  5 13 26 30 12 17 30 14  3 12 17 13 19  7  4 10 19 21 18 25 21 14 16 25 
+23  2  5  1  2 12  3  5 10  1  4  3 17 22  8 23 21 21 15 13 29  9 16 21 13 23 11 24  3 25  9 18 10 26 12 30 18  3 23  2 15  5 30 22 18 26 24  4 17 15 24 17 19 15  2  5  1  6 17 20 22 10  1 28 26 15 19 10 29 10  4  0 27  1  6  9 17 16 25 13 12 10 14  9 20 21 15 12 20  8  7 30 10 29  4 30  4  6 26 13 
+10 27 27  4 13  3 28 26  1 28  7 30  1 12  2 10  6 27  7 11 13 14 24 17  4 11 26  8 12  7  4 22  2 30  5  4 25  8 29  8 24 25 28 10  5 14  6  3 26 14  5 24 17 25 27 18  5 23 15 20 10  5  3 20 28 24 16 18 19 10 20 27  0 22  2 26 16  1 27 24  8 22 23  4 27  5  6  5 16 14  6 21  3 23 23 19 21  3  7  6 
+19  2 28 27 20 30 13  2 15 29 17 28 28 23  1 13 15  5 21 24 21  8 30 16 24 22  7  5  5 25 20 27 20 16 15  9 26 18 29 23  5 27 19 23  2 12 22 14 25 29 24  9 19  6  7 14 10  1 30 25  8 10  8 16 18 23 22 12 29 28 25  1 22  0 18  1 22 25 19 17 28 27  1 14 24  1  3 18 11 16  1  9 24  3 14  2 20 24 15 30 
+ 2  8 22 30 14 21  1 13 29 29  1 20 20 26  8 21 24 23 21 17 12  8 16 25 30  7 18 26 30 22 25 12 15 10 20 18 18 25 28  2 22 23 12  3 16 10 29 12  8 15 25 13 15 10 12  3 30 21 18 23 17 20 11 13  1 17 22 16 19 30 18  6  2 18  0 13 28 27 21 22  4 25 15  5 14  2 16 16  9 26 22  8 19 12 23 22 11  5  6  5 
+ 6 23 12 25  9  5 23 16  9  7 28 26  4 29 29 23 18  8 20 19 13 27 26 29  9 26  7 11 24  4  5 28 28 30 16  4 19 24 18 14 25 30 13  3 11  3 14 10 24  7 13 29 18 28 19 23 28 22 21 17 15  6 13 17 11 12  3  8  2 14  6  9 26  1 13  0 11 10 28 24  7 23  9  3 11 12 12  8 24 21 11 30 22 18 30 15  5  4 17 24 
+ 4  9 15 29 25  5  1 30 30 23 23 22 18 23 16 28 21 11 14  6 21  7 21  4  7 27 19 13  6 29 14 16 29 25 14  5 20 11 28 13 24 30 16  3 18  2  6  4  2 15  6  4  7 23 27 11  5 20 16 27  7 21 10 23 12 29 16  9  9 11  5 17 16 22 28 11  0 23  6 19 16 19 25 15  9 12  2 26  9  4 15 14  7 16 25 17 15  9  7 30 
+26 26 29 30 22 26 12 14 12 28 23 20 13 16 18  6 16 10  5  1  1 23  4  6 19 26 17  5 27 14  5 29 22  7 26  4  5 24  6  5  4 10 15 12 25 24 26  1 26  2  5  5 14  3 24  9 16  4  3 16  2  7  4 25 23 20  7  3  7  4 13 16  1 25 27 10 23  0 21  4 12 28 10  8 24 15  2 14  7  8 22 28  7  4 22 23 23 24 15 17 
+22 16  4 16  5 16 28 22 28 19 23 30 14  8  4 11  3 15 29 30 29  6  5 25 30 10  4 13  6 28 25  7 19  5 24 17 11 20 10 15 11  8 21 22  4  4 24 16 29  7 16  1 21 17 17 11  5  1  3 21 10 19 11 28  4 27 22 28  5 13 26 25 27 19 21 28  6 21  0 11 14 19 21 18 20 29  9  5 23 12 22 26 15  2 24  5 30  1 17 28 
+ 2 10 13 13 16 11 16 28 17  5  7 18 21 27  3  8 28  5  9  2  3  9 14 17 15 12 22 21 17 16 28 20 16 15 28 13 13 15 26 19 15  9  6 24  5 17 15 13 24 28 17  9  5 21 11  7 25 11 11 23 27 24  1 13 17  3 23  5  9 24 30 13 24 17 22 24 19  4 11  0  4  2 26  9 30 16  1 14 13 25 29  9 18 24  2  4  1 27 14 16 
+16 11  2  3 25 27 17 19 16 17 21  1 19 13 30  8 25 21  1 18 17 27  5 12 16 27  5  7 16 30 10 22 20 13  5 13 30 22 16 30 30  6 22 17 21 15 18  6  1 22 27  7 15 24 23  2 22 27  5  3  2 13 30 24  1 15  9  5 22 23 12 12  8 28  4  7 16 12 14  4  0 19  1  5 28 26 22  9 25 10  8 25  2 28 23 13  7 23 29 10 
+30 15 11 30 18  5 28 26 21 27  4 10  8 19  7 11 17 20 26 22 24 26 13  8 13 12  2 28  4 20 26 17 17 20  2 25 26 24 21  5 29 14 12  5 23 17 26  1  6 30  9 25  9 25 27 24 11 20 21 10 19 21 27 22 30 24 20  1  4 20 17 10 22 27 25 23 19 28 19  2 19  0 17  3 22 28 18  1 19 19 13  1 20 20 19 22  1 14 26  9 
+17 19  6  7  6 27 19 19 11 22  1 27 30 21 23  3  5  1  9 10  7 13 20 24 15 29  4 21  6  6 28  6 18 30  8 23 25 23 27  9 23 25 22  2 16 25  2  6 10  7  8 21 25 20 19  8 10 30 12 26 22 15 14 18 13 17  8 11 11 10 30 14 23  1 15  9 25 10 21 26  1 17  0 10  2 30 16  1 13 12 20 26 10  6 17  8 18  5 23 21 
+23  7 10 15  4 16 13 22 29 19 15 28 17  8 23 24  1 24  8  4 16 25 26 23 22 28  2  9  6  9  7 10  4  1 11  4 26 18 13 15 12 10  6 17  9 13 27 20 24 12 24 19  7  3 28 10  2 29  8 13 30 25 13  8  3  1 15 18 28 27 14  9  4 14  5  3 15  8 18  9  5  3 10  0 14  2 16  9 24  8 11 11 12 18 21 15 30  6  8  5 
+20  9 27 27 19 16  5 12  5 15 15 14  6 19 11 28  4  3 19  8 30 24 30 18 22 17 30 14 25 10  4 27 22 14  1 23  3  4  5 10 10 21 14 27  6 19 16  8  6 29 28 27 27 13  2 20 24  9 22 27  7  7 28  4 23 16 16  6 25  6  3 20 27 24 14 11  9 24 20 30 28 22  2 14  0 13 26  3  8 22  1 13  7 21  1 20 29  6 16 12 
+29 23 21 29  3  4 20 16 11 15 11 25 18 19  8  2  9  7 19  2 26 21  9 25 24 20 11 20  8  5 10 17 19 15 21 21 27  8 28 29 13 30 12 13  3 17 17  2 11 18 29 22  5  9 26  2  2 30 10 24  7  9  4  9 15 27 23  1 24 15 12 21  5  1  2 12 12 15 29 16 26 28 30  2 13  0 21 15 25  9 11 25 24 12 25 27  4 12  7 30 
+28 28  7 23 28 12 10 10  7 14  6 15  8 25 28  4 29  1  6  5 19  6 18 17  7 11  9 30 10 26  4 27  7  8  7  3 25 19 19 18 13 12 19 27  6 11  1 28 27  7  6 27 22 16  5 12  2 26 20  1 26 27 27 25 21  8 11  1 27  2 17 15  6  3 16 12  2  2  9  1 22 18 16 16 26 21  0 12  4 26 21 21  5 11 15 17  8 28 26  2 
+ 2 24 24 17 15 22 28 28 21 23 15  5 15 13  7 28  2 28  9 23 22 20 24 13 14 16  7  3 18 30 13 17 10  3 25 12 25  8 18 27 27  5 23  6 28  7 20 18 23 11 13  7  8 21 29  1 27 20  5 13 11  9 24 17  4  8  1  5 10 26 13 12  5 18 16  8 26 14  5 14  9  1  1  9  3 15 12  0  1  6  1 17  9 20  5 22 21 22 15  2 
+15 30 19  9  6 23 20 21 11 10  5 11 27 12 24 27 30 20 25 16  2 19 10 11 27 11 12 28 12 23 28 27 17 27 25  1 12  1  5 17  3 23 17  5 25  6  6 23  6  2 15 24 24 29 25 20 27 25 23 18 24 11 15 25  1 17 29  2 25  4 19 20 16 11  9 24  9  7 23 13 25 19 13 24  8 25  4  1  0 10 10  1  4 23 12 24 13 24 15 24 
+23 20 25  5 22 20 12  9 30 23 30  6 24 28 27 12 10 26 27 21 13 30  3 10 20 18  6 21  2 27 14 26 20 15  9  5 16 27 30 16 13  9  8  4 15 21  8 19 29  8 15  7  1 13 11 23 24  2 13  4  8  5 30 27 27 30 29  8 12 17  7  8 14 16 26 21  4  8 12 25 10 19 12  8 22  9 26  6 10  0  4 21 28 24  9 15 29 26 29 24 
+16 23 10 18 22  9 20  3 30 25 23 21  3 28 26 15 22 30  3 19 22 27 29  3 25 30  2 15 14  1 26 28  6  2 24 25  2 22 22 28 10 18 12  9 17 15  2 23  5  6 11 16 18 28  9 26 29  5 10 25  4 26 28  6  4  6 20 28 16 21  4  7  6  1 22 11 15 22 22 29  8 13 20 11  1 11 21  1 10  4  0 19  2 30 30 25  3  3 24  7 
+ 1 26 27 12 12 10  8  7  7 11 26 24 25 10 17 26 19 22 29 17 15 18 20 19 30 11 21 13 17  8 26 18 21 16  5 29 15  5  4 30 24 15 22 21 13  6 14  4 12  7  1 14 20 29 13  7 24 20  8 10  2  2 12 26 20  4 29 13 29 19 10 30 21  9  8 30 14 28 26  9 25  1 26 11 13 25 21 17  1 21 19  0  8 26 16 22  4 21 23 28 
+16  3 24  1 12 25 26 17  2  4 11  4 29 21 25  3  2  1 29 23 19  7 17 19  3 16  6 17 10 14  1  7 30 11  4  5 28  9 29 25 20  9  3 27 26 19 11  9 19 20  5  5  9 22  3  8 22 13 27 18  4 12 30  5 29 12 11 30  6  8 19 10  3 24 19 22  7  7 15 18  2 20 10 12  7 24  5  9  4 28  2  8  0 11  5  3  6  6  1 23 
+30  5 29 20 15 14 15 18 10 29  8 27 27 28 22 17 16 12 11 22 20 19  3  7  5 21 18 22 27  6 23  6 19 27 13 27 15 13 25 17 29 14 10  1 14 14  7 23  6 13 16  2 30 20 12 23 24 17 21 14  4 19 10 18  3  9  1 26  2 27 21 29 23  3 12 18 16  4  2 24 28 20  6 18 21 12 11 20 23 24 30 26 11  0 24 13 15  6 30 26 
+ 5 28 26 21 22  1 28  3 22  1 20 27  6 16  1 27  9 21 28  4 30  7  6  2 25 25 22 21 20  1 25 23 20  6  7  1 10 25 16 18  5  1 22 15  7 21 17 25  6 23 11  6  3 23 23  5 15  9 28 23 16 22  5  5 27 24  5 18 21  3 18  4 23 14 23 30 25 22 24  2 23 19 17 21  1 25 15  5 12  9 30 16  5 24  0 22 30  5  4  4 
+19 29 24  3 13  9 27  7 22 10 20 30 18 23  4 11 12  8  3 16  4 30 13 26  7  5  6 29 26  6 24 10  8 15 23 19  6  8 20  7 24 26 18 27 29 17  2 14 16 27  5 12  9 20 13 21 25  5  6 14  5  6  5 23 25 10  1 12 18 29 25 30 19  2 22 15 17 23  5  4 13 22  8 15 20 27 17 22 24 15 25 22  3 13 22  0  2 17 21 17 
+20  9 27 13 10 19 23 30 23 17 23 27  2  5 26  2 22 15 11  7 29  6 28  2 29  8  6 28 17 25  9 15 24 30 11 14 28 21 25 18 29 18 19 29 28 25 29  3  6 10 30 22  4 17 15 16 17 11 10 21 22  2 25 26  4 23 25  8 30 21 21  4 21 20 11  5 15 23 30  1  7  1 18 30 29  4  8 21 13 29  3  4  6 15 30  2  0 29 19 12 
+13 10 19 21 10  2 13 29 16 12 23 27 18  2 10  1 28 26 13 20 16 18 26 17  8 21 29 11  9 25  3 18  7  8 29  2  2 23  5 14 18 26 13 28 11  3 19  8  5 19 11 29 17 20 10 16  8  5  7  8 15 11 10 12  4  9  7  5  9 13 14  6  3 24  5  4  9 24  1 27 23 14  5  6  6 12 28 22 24 26  3 21  6  6  5 17 29  0 24 14 
+18 25 30 12 28 17 13 11 26 13 21  9  8 27 14  6 15 23 28 17 18  5 15 26 14 21  7  2 27 21 25 20 16 19 19  9 15 21  5 16  9  5 30 10 15 17  3 18 26  3 19 13  4  2 20 13 20 16 21  5 28 27 12 18 11  9 30  9  2  5 16 26  7 15  6 17  7 15 17 14 29 26 23  8 16  7 26 15 15 29 24 23  1 30  4 21 19 24  0 14 
+23 14  9 19 14  1  1 14  5  6  4  6  5  6 20 18  1 23  9 28 30 10  5 10 26 10  6  3 15 27 16 15  7 15  5 27 12  3  6 13  7 29 17  7 19 10 20 24 23  7 15 29 12 24 28  8  5  2 29 14 22 11  2 19 13 10 20 25 23 18 25 13  6 30  5 24 30 17 28 16 10  9 21  5 12 30  2  2 24 24  7 28 23 26  4 17 12 14 14  0 

+ 1 - 1
examples/knapsackExample.py

@@ -23,7 +23,7 @@ if not os.path.exists('data'):
     os.makedirs('data')
 
 # logging configuration
-logging.basicConfig(format='%(asctime)s %(message)s', filename='data/example.log', level=logging.DEBUG)
+logging.basicConfig(format='%(asctime)s %(message)s', filename='data/example_knapsack.log', level=logging.DEBUG)
 
 random.seed(42)
 

+ 1 - 1
examples/knapsackMultiExample.py

@@ -24,7 +24,7 @@ if not os.path.exists('data'):
     os.makedirs('data')
 
 # logging configuration
-logging.basicConfig(format='%(asctime)s %(message)s', filename='data/exampleMOEAD.log', level=logging.DEBUG)
+logging.basicConfig(format='%(asctime)s %(message)s', filename='data/example_MOEAD_knapsack.log', level=logging.DEBUG)
 
 random.seed(42)
 

+ 80 - 0
examples/qapExample.py

@@ -0,0 +1,80 @@
+# main imports
+import logging
+import os
+import random
+import numpy as np
+
+# module imports
+from macop.solutions.discrete import CombinatoryIntegerSolution
+from macop.evaluators.discrete.mono import QAPEvaluator
+
+from macop.operators.discrete.mutators import SimpleMutation
+
+from macop.policies.classicals import RandomPolicy
+from macop.policies.reinforcement import UCBPolicy
+
+from macop.algorithms.mono import IteratedLocalSearch as ILS
+from macop.algorithms.mono import HillClimberFirstImprovment
+from macop.callbacks.classicals import BasicCheckpoint
+
+if not os.path.exists('data'):
+    os.makedirs('data')
+
+# logging configuration
+logging.basicConfig(format='%(asctime)s %(message)s', filename='data/example_qap.log', level=logging.DEBUG)
+
+random.seed(42)
+
+# usefull instance data
+n = 100
+qap_instance_file = 'instances/qap/qap_instance.txt'
+filepath = "data/checkpoints_qap.csv"
+
+
+# default validator
+def validator(solution):
+    if len(list(solution._data)) > len(set(list(solution._data))):
+        print("not valid")
+        return False
+    return True
+
+# define init random solution
+def init():
+    return CombinatoryIntegerSolution.random(n, validator)
+
+
+def main():
+
+    with open(qap_instance_file, 'r') as f:
+        file_data = f.readlines()
+        print(f'Instance information {file_data[0]}')
+
+        D_lines = file_data[1:n + 1]
+        D_data = ''.join(D_lines).replace('\n', '')
+
+        F_lines = file_data[n:2 * n + 1]
+        F_data = ''.join(F_lines).replace('\n', '')
+
+    D_matrix = np.fromstring(D_data, dtype=float, sep=' ').reshape(n, n)
+    print(f'D matrix shape: {D_matrix.shape}')
+    F_matrix = np.fromstring(F_data, dtype=float, sep=' ').reshape(n, n)
+    print(f'F matrix shape: {F_matrix.shape}')
+
+    operators = [SimpleMutation()]
+    policy = RandomPolicy(operators)
+    callback = BasicCheckpoint(every=5, filepath=filepath)
+    evaluator = QAPEvaluator(data={'F': F_matrix, 'D': D_matrix})
+
+    # passing global evaluation param from ILS
+    hcfi = HillClimberFirstImprovment(init, evaluator, operators, policy, validator, maximise=False, verbose=True)
+    algo = ILS(init, evaluator, operators, policy, validator, localSearch=hcfi, maximise=False, verbose=True)
+    
+    # add callback into callback list
+    algo.addCallback(callback)
+
+    bestSol = algo.run(100000, ls_evaluations=100)
+
+    print('Solution score is {}'.format(evaluator.compute(bestSol)))
+
+if __name__ == "__main__":
+    main()

+ 76 - 0
examples/ubqpExample.py

@@ -0,0 +1,76 @@
+# main imports
+import logging
+import os
+import random
+
+# module imports
+from macop.solutions.discrete import BinarySolution
+from macop.evaluators.discrete.mono import KnapsackEvaluator
+
+from macop.operators.discrete.mutators import SimpleMutation
+from macop.operators.discrete.mutators import SimpleBinaryMutation
+from macop.operators.discrete.crossovers import SimpleCrossover
+from macop.operators.discrete.crossovers import RandomSplitCrossover
+
+from macop.policies.classicals import RandomPolicy
+from macop.policies.reinforcement import UCBPolicy
+
+from macop.algorithms.mono import IteratedLocalSearch as ILS
+from macop.algorithms.mono import HillClimberFirstImprovment
+from macop.callbacks.classicals import BasicCheckpoint
+
+if not os.path.exists('data'):
+    os.makedirs('data')
+
+# logging configuration
+logging.basicConfig(format='%(asctime)s %(message)s', filename='data/example.log', level=logging.DEBUG)
+
+random.seed(42)
+
+elements_score = [ random.randint(1, 20) for _ in range(30) ]
+elements_weight = [ random.randint(2, 5) for _ in range(30) ]
+
+def knapsackWeight(solution):
+
+    weight_sum = 0
+    for index, elem in enumerate(solution._data):
+        weight_sum += elements_weight[index] * elem
+
+    return weight_sum
+
+# default validator
+def validator(solution):
+
+    if knapsackWeight(solution) <= 80:
+        return True
+    else:
+        False
+
+# define init random solution
+def init():
+    return BinarySolution.random(30, validator)
+
+
+filepath = "data/checkpoints.csv"
+
+def main():
+
+    operators = [SimpleBinaryMutation(), SimpleMutation(), SimpleCrossover(), RandomSplitCrossover()]
+    policy = UCBPolicy(operators)
+    callback = BasicCheckpoint(every=5, filepath=filepath)
+    evaluator = KnapsackEvaluator(data={'worths': elements_score})
+
+    # passing global evaluation param from ILS
+    hcfi = HillClimberFirstImprovment(init, evaluator, operators, policy, validator, maximise=True, verbose=False)
+    algo = ILS(init, evaluator, operators, policy, validator, localSearch=hcfi, maximise=True, verbose=False)
+    
+    # add callback into callback list
+    algo.addCallback(callback)
+
+    bestSol = algo.run(1000)
+
+    print('Solution score is {}'.format(evaluator.compute(bestSol)))
+    print('Solution weigth is {}'.format(knapsackWeight(bestSol)))
+
+if __name__ == "__main__":
+    main()

+ 58 - 2
macop/evaluators/discrete/mono.py

@@ -1,11 +1,11 @@
-"""Knapsack evaluators classes
+"""Mono-objective evaluators classes
 """
 # main imports
 from macop.evaluators.base import Evaluator
 
 
 class KnapsackEvaluator(Evaluator):
-    """Knapsack evaluator class which enables to compute solution using specific `_data`
+    """Knapsack evaluator class which enables to compute knapsack solution using specific `_data`
 
     - stores into its `_data` dictionary attritute required measures when computing a knapsack solution
     - `_data['worths']` stores knapsack objects worths information
@@ -42,3 +42,59 @@ class KnapsackEvaluator(Evaluator):
             fitness += self._data['worths'][index] * elem
 
         return fitness
+
+
+class QAPEvaluator(Evaluator):
+    """QAP evaluator class which enables to compute qap solution using specific `_data`
+
+    Solutions use for this evaluator are with type of `macop.solutions.discrete.CombinatoryIntegerSolution`
+
+    - stores into its `_data` dictionary attritute required measures when computing a QAP solution
+    - `_data['F']` matrix of size n x n with flows data between facilities (stored as numpy array)
+    - `_data['D']` matrix of size n x n with distances data between locations (stored as numpy array)
+    - `compute` method enables to compute and associate a score to a given QAP solution
+
+    Example:
+
+    >>> import random
+    >>> # combinatory solution import
+    >>> from macop.solutions.discrete import CombinatoryIntegerSolution
+    >>> # evaluator import
+    >>> from macop.evaluators.discrete.QAPEvaluator import QAPEvaluator
+    >>> # define problem data using QAP example instance
+    >>> qap_instance_file = '../../../examples/instances/qap/qap_instance.txt'
+    >>> n = 100 # problem size
+    >>> size = len(solution_data)
+    >>> # loading data
+    >>> f = open(qap_instance_file, 'r')
+    >>> file_data = f.readlines()
+    >>> D_lines = file_data[1:n + 1]
+    >>> D_data = ''.join(D_lines).replace('\\n', '')
+    >>> F_lines = file_data[n:2 * n + 1]
+    >>> F_data = ''.join(F_lines).replace('\\n', '')
+    >>> D_matrix = np.fromstring(D_data, dtype=float, sep=' ').reshape(n, n)
+    >>> F_matrix = np.fromstring(F_data, dtype=float, sep=' ').reshape(n, n)
+    >>> f.close()    
+    >>> # create evaluator instance using loading data
+    >>> evaluator = QAPEvaluator(data={'F': F_matrix, 'D': D_matrix})
+    >>> # create new random combinatory solution using n, the instance QAP size
+    >>> solution = CombinatoryIntegerSolution.random(n)
+    >>> # compute solution score
+    >>> evaluator.compute(solution)
+    40
+    """
+    def compute(self, solution):
+        """Apply the computation of fitness from solution
+
+        Args:
+            solution: {Solution} -- QAP solution instance
+    
+        Returns:
+            {float} -- fitness score of solution
+        """
+        fitness = 0
+        for index_i, val_i in enumerate(solution._data):
+            for index_j, val_j in enumerate(solution._data):
+                fitness += self._data['F'][index_i, index_j] * self._data['D'][val_i, val_j]
+
+        return fitness

+ 1 - 1
macop/solutions/discrete.py

@@ -84,7 +84,7 @@ class CombinatoryIntegerSolution(Solution):
     """
     Combinatory integer solution class
 
-    - store solution as a binary array (example: [0, 1, 0, 1, 1])
+    - store solution as a combinatory array (example: [1, 3, 0, 2])
     - associated size is the size of the array
     - mainly use for selecting or not an element in a list of valuable objects
 

+ 1 - 1
setup.py

@@ -73,7 +73,7 @@ class TestCommand(distutils.command.check.check):
 
 setup(
     name='macop',
-    version='1.0.8',
+    version='1.0.9',
     description='Minimalist And Customisable Optimisation Package',
     long_description=open('README.md').read(),
     long_description_content_type='text/markdown',