Outranking algorithms

This notebook is dedicated to the use of outranking algorithms, including the different ELECTRE algorithms and Promethee algorithms.

[1]:
%matplotlib notebook
%config Completer.use_jedi = False

Electre algorithms

Outranking problem formalization

[2]:
from mcda.matrices import *
from mcda.relations import *
from mcda.scales import *
from mcda.outranking.electre import *
[3]:
#Parameters
alternatives = ["Peugeot 505 GR",
    "Opel Record 2000 LS",
    "Citroen Visa Super E",
    "VW Golf 1300 GLS",
    "Citroen CX 2400 Pallas"]
scales = {
    0: QuantitativeScale(1, 5),
    1: QuantitativeScale(1, 5),
    2: QuantitativeScale(1, 5),
    3: QuantitativeScale(1, 5),
    4: QuantitativeScale(1, 5),
    5: QuantitativeScale(1, 5),
    6: QuantitativeScale(1, 5),
}
dataset = PerformanceTable(
    [
        [4, 2, 1, 5, 2, 2, 4],
        [3, 5, 3, 5, 3, 3, 3],
        [3, 5, 3, 5, 3, 2, 2],
        [4, 2, 2, 5, 1, 1, 1],
        [4, 1, 3, 5, 4, 1, 5],
    ],
    alternatives=alternatives,
    scales=scales
)

Electre I

[4]:
W = {
    0: 0.780, 1: 1.180, 2: 1.570, 3: 3.140,
    4: 2.350, 5: 0.390, 6: 0.590}
c_hat = 0.75
d_hat = {0: 2, 1: 2, 2: 2, 3: 2, 4: 2, 5: 2, 6: 2}
[5]:
electre1 = Electre1(dataset, W, c_hat, d_hat)

concordance matrix

[6]:
electre1.concordance().data
[6]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 1.000 0.451 0.490 0.843 0.549
Opel Record 2000 LS 0.863 1.000 1.000 0.922 0.628
Citroen Visa Super E 0.863 0.902 1.000 0.922 0.628
VW Golf 1300 GLS 0.667 0.392 0.392 1.000 0.549
Citroen CX 2400 Pallas 0.843 0.843 0.843 0.882 1.000
[7]:
dataset.scales[0] = QuantitativeScale(1, 5, preference_direction=MIN)
concordance_mat = electre1.concordance()
concordance_mat.data
[7]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 1.000 0.373 0.412 0.843 0.549
Opel Record 2000 LS 0.941 1.000 1.000 1.000 0.706
Citroen Visa Super E 0.941 0.902 1.000 1.000 0.706
VW Golf 1300 GLS 0.667 0.314 0.314 1.000 0.549
Citroen CX 2400 Pallas 0.843 0.765 0.765 0.882 1.000

discordance matrix

[8]:
discordance_mat = electre1.discordance()
discordance_mat.criteria_matrices[0].data
[8]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 0 1 1 0 0
Opel Record 2000 LS 0 0 0 0 0
Citroen Visa Super E 0 0 0 0 0
VW Golf 1300 GLS 0 1 1 0 0
Citroen CX 2400 Pallas 0 1 1 0 0

outranking matrix

[9]:
outranking_matrix = electre1.outranking(concordance_mat, discordance_mat)
outranking_matrix.data
[9]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 1 0 0 1 0
Opel Record 2000 LS 1 1 1 1 0
Citroen Visa Super E 1 1 1 1 0
VW Golf 1300 GLS 0 0 0 1 0
Citroen CX 2400 Pallas 1 0 0 1 1
[10]:
PreferenceStructure.from_outranking_matrix(outranking_matrix)
[10]:
PreferenceStructure([PreferenceRelation(Peugeot 505 GR, VW Golf 1300 GLS), IndifferenceRelation(Opel Record 2000 LS, Citroen Visa Super E), IncomparableRelation(Opel Record 2000 LS, Citroen CX 2400 Pallas), PreferenceRelation(Opel Record 2000 LS, Peugeot 505 GR), IncomparableRelation(Citroen Visa Super E, Citroen CX 2400 Pallas), PreferenceRelation(Opel Record 2000 LS, VW Golf 1300 GLS), PreferenceRelation(Citroen CX 2400 Pallas, VW Golf 1300 GLS), PreferenceRelation(Citroen CX 2400 Pallas, Peugeot 505 GR), PreferenceRelation(Citroen Visa Super E, Peugeot 505 GR), PreferenceRelation(Citroen Visa Super E, VW Golf 1300 GLS)])
[11]:
PreferenceStructure.from_outranking_matrix(outranking_matrix).outranking_matrix.data
[11]:
Citroen CX 2400 Pallas Citroen Visa Super E Opel Record 2000 LS Peugeot 505 GR VW Golf 1300 GLS
Citroen CX 2400 Pallas 1 0 0 1 1
Citroen Visa Super E 0 1 1 1 1
Opel Record 2000 LS 0 1 1 1 1
Peugeot 505 GR 0 0 0 1 1
VW Golf 1300 GLS 0 0 0 0 1
[12]:
outranking_matrix.plot()
[12]:
../../_images/notebooks_examples_outranking_algorithms_17_0.svg

We can also construct the outranking matrix using the method construct:

[13]:
outranking_matrix = electre1.construct()

Exploitation

[14]:
electre1.exploit(outranking_matrix)
[14]:
['Peugeot 505 GR',
 'Opel Record 2000 LS',
 'Citroen Visa Super E',
 'VW Golf 1300 GLS',
 'Citroen CX 2400 Pallas']
[15]:
electre1.exploit(outranking_matrix, cycle_reduction=True)
[15]:
['Citroen Visa Super E', 'Citroen CX 2400 Pallas', 'Opel Record 2000 LS']
[16]:
electre1.exploit(
    outranking_matrix, cycle_reduction=True, transitivity=True
)
[16]:
['Citroen Visa Super E', 'Citroen CX 2400 Pallas', 'Opel Record 2000 LS']
[17]:
electre1.select(
    cycle_reduction=True, transitivity=True
)
[17]:
['Citroen Visa Super E', 'Citroen CX 2400 Pallas', 'Opel Record 2000 LS']

Electre II

Init

[18]:
#Parameters
alternatives = [
    "Peugeot 505 GR",
    "Opel Record 2000 LS",
    "Citroen Visa Super E",
    "VW Golf 1300 GLS",
    "Citroen CX 2400 Pallas"
]
scales = {
    0: QuantitativeScale(1, 5),
    1: QuantitativeScale(1, 5),
    2: QuantitativeScale(1, 5),
    3: QuantitativeScale(1, 5),
    4: QuantitativeScale(1, 5),
    5: QuantitativeScale(1, 5),
    6: QuantitativeScale(1, 5),
}
dataset = PerformanceTable([
        [1, 2, 1, 5, 2, 2, 4],  # a1
        [3, 5, 3, 5, 3, 3, 3],  # a2
        [3, 5, 3, 5, 3, 2, 2],  # a3
        [1, 2, 2, 5, 1, 1, 1],  # a4
        [1, 1, 3, 5, 4, 1, 5],  # a5
    ], alternatives=alternatives, scales=scales
)
W = {
    0: 0.780, 1: 1.180, 2: 1.570, 3: 3.140,
    4: 2.350, 5: 0.390, 6: 0.590
}

electre2 = Electre2(
    dataset, W, 0.65, 0.85,
    {c: 2 for c in dataset.criteria},
    {c: 1 for c in dataset.criteria}
)

concordance and discordance

First let’s compute the concordance and discordance as it done in Electre 1

[19]:
concordance_matrix = electre2.concordance()
discordance_matrix = electre2.discordance()
print(concordance_matrix.data)
discordance_matrix.criteria_matrices[0].data
                        Peugeot 505 GR  Opel Record 2000 LS  \
Peugeot 505 GR                   1.000                0.373
Opel Record 2000 LS              0.941                1.000
Citroen Visa Super E             0.941                0.902
VW Golf 1300 GLS                 0.667                0.314
Citroen CX 2400 Pallas           0.843                0.765

                        Citroen Visa Super E  VW Golf 1300 GLS  \
Peugeot 505 GR                         0.412             0.843
Opel Record 2000 LS                    1.000             1.000
Citroen Visa Super E                   1.000             1.000
VW Golf 1300 GLS                       0.314             1.000
Citroen CX 2400 Pallas                 0.765             0.882

                        Citroen CX 2400 Pallas
Peugeot 505 GR                           0.549
Opel Record 2000 LS                      0.706
Citroen Visa Super E                     0.706
VW Golf 1300 GLS                         0.549
Citroen CX 2400 Pallas                   1.000
[19]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 0 2 2 0 0
Opel Record 2000 LS 0 0 0 0 0
Citroen Visa Super E 0 0 0 0 0
VW Golf 1300 GLS 0 2 2 0 0
Citroen CX 2400 Pallas 0 2 2 0 0
[20]:
strong_outranking = electre2.outranking(
    concordance_matrix,
    discordance_matrix
)
strong_outranking.data
[20]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 1 0 0 0 0
Opel Record 2000 LS 1 1 1 1 0
Citroen Visa Super E 0 0 1 1 0
VW Golf 1300 GLS 0 0 0 1 0
Citroen CX 2400 Pallas 0 0 0 1 1
[21]:
weak_outranking = electre2.outranking(
    concordance_matrix,
    discordance_matrix,
    strong=False
)
weak_outranking.data
[21]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 1 0 0 1 0
Opel Record 2000 LS 1 1 1 1 0
Citroen Visa Super E 1 0 1 1 0
VW Golf 1300 GLS 0 0 0 1 0
Citroen CX 2400 Pallas 1 0 0 1 1

You can also return both matrices directly:

[22]:
strong_outranking, weak_outranking = electre2.construct()

Distillation

Now let’s process the ascending and descending distallation

[23]:
ascending_distillate = electre2.distillation(
    strong_outranking,
    weak_outranking,
    ascending=True
)
descending_distillate = electre2.distillation(
    strong_outranking,
    weak_outranking
)
[24]:
ascending_distillate.data
[24]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 1 0 0 1 0
Opel Record 2000 LS 1 1 1 1 1
Citroen Visa Super E 1 0 1 1 1
VW Golf 1300 GLS 0 0 0 1 0
Citroen CX 2400 Pallas 1 0 1 1 1
[25]:
ascending_distillate.plot()
[25]:
../../_images/notebooks_examples_outranking_algorithms_37_0.svg
[26]:
descending_distillate.plot()
[26]:
../../_images/notebooks_examples_outranking_algorithms_38_0.svg

final ranking

Finally, we can compute and print the final ranking

[27]:
final_rank = ascending_distillate & descending_distillate
final_rank.data
[27]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 1 0 0 1 0
Opel Record 2000 LS 1 1 1 1 1
Citroen Visa Super E 1 0 1 1 0
VW Golf 1300 GLS 0 0 0 1 0
Citroen CX 2400 Pallas 1 0 1 1 1
[28]:
final_rank.plot()
[28]:
../../_images/notebooks_examples_outranking_algorithms_41_0.svg

We could also directly call the exploit method:

[29]:
final_rank = electre2.exploit((strong_outranking, weak_outranking))

Direct methods

We can also compute directly the electre II algorithm if nothing needs to be changed. Besides it’s possible to reduce the matrix in term of preferences for a proper graph.

[30]:
final_rank = electre2.rank()
final_rank.data
[30]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas
Peugeot 505 GR 1 0 0 1 0
Opel Record 2000 LS 1 1 1 1 1
Citroen Visa Super E 1 0 1 1 0
VW Golf 1300 GLS 0 0 0 1 0
Citroen CX 2400 Pallas 1 0 1 1 1
[31]:
final_rank.plot()
[31]:
../../_images/notebooks_examples_outranking_algorithms_46_0.svg

Electre III

init

[32]:
alternatives = [
    "Peugeot 505 GR",
    "Opel Record 2000 LS",
    "Citroen Visa Super E",
    "VW Golf 1300 GLS",
    "Citroen CX 2400 Pallas",
    "Renault Scenic"
]
scales = {
    0: QuantitativeScale(7, 10),
    1: QuantitativeScale(7, 10),
    2: QuantitativeScale(5, 9),
    3: QuantitativeScale(6, 9),
}
dataset = PerformanceTable(
    [
        [8.84, 8.79, 6.43, 6.95],
        [8.57, 8.51, 5.47, 6.91],
        [7.76, 7.75, 5.34, 8.76],
        [7.97, 9.12, 5.93, 8.09],
        [9.03, 8.97, 8.19, 8.10],
        [7.41, 7.87, 6.77, 7.23],
    ],
    alternatives=alternatives, scales=scales
)
W = {0: 9.00, 1: 8.24, 2: 5.98, 3: 8.48}
P = {0: 0.50, 1: 0.50, 2: 0.50, 3: 0.50}
I = {0: 0.30, 1: 0.30, 2: 0.30, 3: 0.30}
V = {0: 0.70, 1: 0.70, 2: 0.70, 3: 0.70}

electre3 = Electre3(dataset, W, I, P, V)

concordance

[33]:
electre3.concordance().data
[33]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas Renault Scenic
Peugeot 505 GR 1.000000 1.000000 0.732492 0.693502 0.543849 0.962271
Opel Record 2000 LS 0.811356 1.000000 0.732492 0.321640 0.108770 0.784606
Citroen Visa Super E 0.267508 0.456151 1.000000 0.551420 0.267508 0.811356
VW Golf 1300 GLS 0.527445 0.716088 0.732492 1.000000 0.527445 0.811356
Citroen CX 2400 Pallas 1.000000 1.000000 0.732492 1.000000 1.000000 1.000000
Renault Scenic 0.456151 0.456151 0.661514 0.188644 0.000000 1.000000

discordance

[34]:
d = electre3.discordance().data
[35]:
for i in d.index:
    for j in d.columns:
        print(d.loc[i, j].tolist())
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 1]
[0, 0, 0, 1]
[0, 0, 1, 1]
[0, 0, 0, 0]
[0, 0, 1, 0]
[0, 0, 0, 0]
[0, 0, 0, 1]
[0.0, 0.5499999999999973, 0.0, 1.0]
[0, 0, 1, 1]
[0, 0, 1, 0]
[1, 1, 1, 0]
[1, 1, 0, 0]
[0, 0, 0, 0]
[0.0, 1.0, 0.4499999999999994, 0.0]
[1, 1, 1, 0]
[0, 0, 1, 0]
[1, 0, 0, 0]
[0.5000000000000028, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.8499999999999999]
[0, 0, 0, 0]
[1, 0, 1, 0]
[0, 0, 1, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0.0, 0.0, 0.0, 0.8000000000000009]
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0]
[1, 1, 0, 0]
[1.0, 0.6999999999999985, 0.0, 0.0]
[0, 0, 0, 1]
[0.2999999999999981, 1.0, 0.0, 1.0]
[1, 1, 1, 1]
[0, 0, 0, 0]

credibility

[36]:
credibility = electre3.construct()
credibility.data
[36]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas Renault Scenic
Peugeot 505 GR 1.0 1.000000 0.000000 0.0 0.0 0.962271
Opel Record 2000 LS 0.0 1.000000 0.000000 0.0 0.0 0.000000
Citroen Visa Super E 0.0 0.000000 1.000000 0.0 0.0 0.000000
VW Golf 1300 GLS 0.0 0.716088 0.410731 1.0 0.0 0.000000
Citroen CX 2400 Pallas 1.0 1.000000 0.547642 1.0 1.0 1.000000
Renault Scenic 0.0 0.000000 0.000000 0.0 0.0 1.000000

qualification

[37]:
qual = electre3.qualification(credibility)
qual
[37]:
Peugeot 505 GR            1
Opel Record 2000 LS      -2
Citroen Visa Super E      0
VW Golf 1300 GLS         -1
Citroen CX 2400 Pallas    4
Renault Scenic           -2
dtype: int64

Distillation

[38]:
descending_distillate = electre3.distillation(
    credibility,
)
descending_distillate.data
[38]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas Renault Scenic
Peugeot 505 GR 1 1 1 1 0 1
Opel Record 2000 LS 0 1 1 1 0 1
Citroen Visa Super E 0 1 1 1 0 1
VW Golf 1300 GLS 0 1 1 1 0 1
Citroen CX 2400 Pallas 1 1 1 1 1 1
Renault Scenic 0 1 1 1 0 1
[39]:
ascending_distillate = electre3.distillation(
    credibility,
    ascending=True
)
ascending_distillate.data
[39]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas Renault Scenic
Peugeot 505 GR 1 1 0 1 0 1
Opel Record 2000 LS 0 1 0 0 0 1
Citroen Visa Super E 1 1 1 1 1 1
VW Golf 1300 GLS 1 1 0 1 0 1
Citroen CX 2400 Pallas 1 1 1 1 1 1
Renault Scenic 0 1 0 0 0 1
[40]:
ascending_distillate.plot()
[40]:
../../_images/notebooks_examples_outranking_algorithms_62_0.svg
[41]:
descending_distillate.plot()
[41]:
../../_images/notebooks_examples_outranking_algorithms_63_0.svg

Final ranking

[42]:
ranking = ascending_distillate & descending_distillate
ranking.data
[42]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas Renault Scenic
Peugeot 505 GR 1 1 0 1 0 1
Opel Record 2000 LS 0 1 0 0 0 1
Citroen Visa Super E 0 1 1 1 0 1
VW Golf 1300 GLS 0 1 0 1 0 1
Citroen CX 2400 Pallas 1 1 1 1 1 1
Renault Scenic 0 1 0 0 0 1
[43]:
ranking.plot()
[43]:
../../_images/notebooks_examples_outranking_algorithms_66_0.svg

You can also call the exploit method directly:

[44]:
ranking = electre3.exploit(credibility)

Direct methods

We can also compute directly the electre III algorithm if nothing needs to be change. Besides it’s possible to reduce the matrix in term of preferences for a proper graph.

[45]:
final_rank = electre3.rank()
final_rank.data
[45]:
Peugeot 505 GR Opel Record 2000 LS Citroen Visa Super E VW Golf 1300 GLS Citroen CX 2400 Pallas Renault Scenic
Peugeot 505 GR 1 1 0 1 0 1
Opel Record 2000 LS 0 1 0 0 0 1
Citroen Visa Super E 0 1 1 1 0 1
VW Golf 1300 GLS 0 1 0 1 0 1
Citroen CX 2400 Pallas 1 1 1 1 1 1
Renault Scenic 0 1 0 0 0 1
[46]:
final_rank.plot()
[46]:
../../_images/notebooks_examples_outranking_algorithms_71_0.svg

Electre TRI

Init

[47]:
scales = {
    0: QuantitativeScale(0, 1),
    1: QuantitativeScale(3, 4),
    2: QuantitativeScale(1, 2),
    3: QuantitativeScale(0, 1),
    4: QuantitativeScale(30, 100),
}
dataset = PerformanceTable([
    [0.720, 3.560, 1.340, 0.62, 44.340],
    [0.8, 3.940, 1.430, 0.74, 36.360],
    [0.760, 3.630, 1.380, 0.89, 48.750],
    [0.780, 3.740, 1.450, 0.72, 42.130],
    [0.740, 3.540, 1.370, 0.73, 36.990],
    [0.690, 3.740, 1.450, 0.84, 42.430],
    [0.7, 3.280, 1.280, 0.83, 47.430],
    [0.860, 3.370, 1.150, 0.8, 80.790],
], scales=scales)
w = {0: 30, 1: 30, 2: 20, 3: 10, 4: 10}
P = {0: 0.05, 1: 0.1, 2: 0.05, 3: 0.1, 4: 8}
I = {0: 0.02, 1: 0.05, 2: 0.02, 3: 0.05, 4: 2}
V = {0: 0.15, 1: 0.6, 2: 0.25, 3: 0.25, 4: 15}
profiles = PerformanceTable(
    [
        [0.750, 3.500, 1.300, 0.730, 42.00],
        [0.800, 3.700, 1.370, 0.790, 43.000],
    ],
    alternatives=["p1", "p2"],
    scales=scales
)
categories = ["Low", "Medium", "High"]

electre_tri = ElectreTri(
    dataset, W, profiles, I, P, V, lambda_=0.7, categories=categories
)

Construction step

[48]:
credibility = electre_tri.construct()
credibility.data
[48]:
0 1 2 3 4 5 6 7 p1 p2
0 1.000000 0.000000 0.000000 0.000000 0.669611 0.077514 0.730189 0.0 0.637855 0.061431
1 1.000000 1.000000 0.732492 1.000000 1.000000 0.732492 0.785994 0.0 1.000000 1.000000
2 1.000000 0.329298 1.000000 0.551420 1.000000 0.551420 1.000000 0.0 1.000000 0.706751
3 1.000000 0.740063 0.732492 1.000000 1.000000 0.732492 0.732492 0.0 1.000000 0.892997
4 1.000000 0.146081 0.510641 0.362145 1.000000 0.283912 0.732492 0.0 1.000000 0.402650
5 0.905363 0.335499 0.716088 0.716088 0.716088 1.000000 1.000000 0.0 0.716088 0.716088
6 0.551420 0.000000 0.129903 0.053363 0.362145 0.306916 1.000000 0.0 0.456151 0.089744
7 0.368776 0.000000 0.050924 0.000000 0.184388 0.000000 0.811356 1.0 0.551420 0.184388
p1 0.822250 0.095726 0.237885 0.420441 0.811356 0.198238 0.732492 0.0 1.000000 0.214006
p2 1.000000 0.551420 0.732492 0.811356 1.000000 0.811356 1.000000 0.0 1.000000 1.000000

Optimistic Procedure

[49]:
electre_tri.exploit(
    credibility
).data
[49]:
0       Low
1      High
2      High
3      High
4    Medium
5      High
6       Low
7      High
dtype: object

Pessimistic Procedure

[50]:
electre_tri.exploit(
    credibility,
    pessimistic=True
).data
[50]:
0       Low
1      High
2      High
3      High
4    Medium
5      High
6       Low
7       Low
dtype: object

Direct method

[51]:
electre_tri.assign().data
[51]:
0       Low
1      High
2      High
3      High
4    Medium
5      High
6       Low
7      High
dtype: object
[52]:
electre_tri.assign(pessimistic=True).data
[52]:
0       Low
1      High
2      High
3      High
4    Medium
5      High
6       Low
7       Low
dtype: object

Promethee algorithms

Outranking problem formalization

[53]:
from mcda import PerformanceTable
from mcda.functions import UShapeFunction, VShapeFunction, LevelFunction, GaussianFunction
from mcda.outranking.promethee import *
from mcda.scales import *
[54]:
action_names = ['a1', 'a2', 'a3', 'a4', 'a5']

scales = {
    0: QuantitativeScale(-5, 5, MAX),
    1: QuantitativeScale(-5, 5, MAX),
    2: QuantitativeScale(-5, 5, MAX),
    3: QuantitativeScale(-5, 5, MAX),
    4: QuantitativeScale(-5, 5, MAX),
    5: QuantitativeScale(-5, 5, MAX),
}

dataset = PerformanceTable([
    [1, 2, -1, 5, 2, 2],  # a1
    [3, 5, 3, -5, 3, 3],  # a2
    [3, -5, 3, 4, 3, 2],  # a3
    [2, -2, 2, 5, 1, 1],  # a4
    [3, 5, 3, -5, 3, 3],  # a5
], scales=scales, alternatives=action_names)

Promethee I

[55]:
preference_func_list = {
    0: VShapeFunction(p=1),
    1: VShapeFunction(p=4),
    2: VShapeFunction(p=3),
    3: VShapeFunction(p=1),
    4: VShapeFunction(p=2),
    5: VShapeFunction(p=2)
}
W = {0: 0.5, 1: 3, 2: 1.5, 3: 0.2, 4: 2, 5: 1}
[56]:
promethee1 = Promethee1(dataset, W, preference_func_list)
[57]:
res = promethee1.rank()
res
[57]:
PreferenceStructure([PreferenceRelation(a2, a1), PreferenceRelation(a5, a1), PreferenceRelation(a3, a4), PreferenceRelation(a2, a3), PreferenceRelation(a5, a3), IncomparableRelation(a1, a3), PreferenceRelation(a2, a4), PreferenceRelation(a5, a4), PreferenceRelation(a1, a4), IndifferenceRelation(a2, a5)])
[58]:
res.plot()
[58]:
../../_images/notebooks_examples_outranking_algorithms_91_0.svg

Promethee II

[59]:
promethee2 = Promethee2(dataset, W, preference_func_list)
[60]:
res = promethee2.rank()
res.data
[60]:
a1   -1.024390
a2    1.908537
a3   -0.701220
a4   -2.091463
a5    1.908537
dtype: float64
[61]:
PreferenceStructure.from_ranking(res).plot()
[61]:
../../_images/notebooks_examples_outranking_algorithms_95_0.svg

Promethee GAIA

[62]:
gaia = PrometheeGaia(dataset, W, preference_func_list)
[63]:
gaia.plot()

SRMP

[64]:
from mcda import PerformanceTable
from mcda.scales import *
from mcda.outranking.srmp import *
from mcda.relations import PreferenceStructure
[65]:
alternatives = ["Fiat 500", "Peugeot 309", "Renault Clio", "Opel Astra", "Honda Civic", "Toyota Corolla"]
criteria = ["cost", "fuel consumption", "comfort", "color", "range"]
scale1 = QuantitativeScale(6000, 20000, preference_direction=MIN)
scale2 = QuantitativeScale(4, 6, preference_direction=MIN)
scale3 = QualitativeScale({"*": 1, "**": 2, "***": 3, "****": 4})
scale4 = QualitativeScale({"red": 1, "blue": 2, "black": 3, "grey": 4}, preference_direction=MIN)
scale5 = QuantitativeScale(400, 1000)
scales = {
    criteria[0]: scale1,
    criteria[1]: scale2,
    criteria[2]: scale3,
    criteria[3]: scale4,
    criteria[4]: scale5
}
performance_table = PerformanceTable(
    [
        [9500, 4.2, "**", "blue", 450],
        [15600, 4.5, "****", "black", 900],
        [6800, 4.1, "***", "grey", 700],
        [10200, 5.6, "****", "black", 850],
        [8100, 5.2, "***", "red", 750],
        [12000, 4.9, "****", "grey", 850]
    ],
    alternatives=alternatives,
    criteria=criteria,
    scales=scales
)
[66]:
criteria_weights = {
    criteria[0]: 1,
    criteria[1]: 2,
    criteria[2]: 3,
    criteria[3]: 2,
    criteria[4]: 4
}

profiles = PerformanceTable(
    [
        [15000, 5.5, "**", "grey", 500],
        [10000, 5, "***", "black", 700],
        [7000, 4.5, "****", "blue", 900],
    ],
    criteria=criteria,
    scales=scales
)

lexicographic_order = [2, 0, 1]
srmp = SRMP(performance_table, criteria_weights, profiles, lexicographic_order)

Preference relations

[67]:
preference_matrices = srmp.construct()
preference_matrices[0].data
[67]:
Fiat 500 Peugeot 309 Renault Clio Opel Astra Honda Civic Toyota Corolla
Fiat 500 1 0 0 0 0 0
Peugeot 309 1 1 0 1 0 0
Renault Clio 1 1 1 1 1 1
Opel Astra 1 0 0 1 0 0
Honda Civic 1 1 1 1 1 1
Toyota Corolla 1 1 1 1 1 1
[68]:
preference_matrices[1].data
[68]:
Fiat 500 Peugeot 309 Renault Clio Opel Astra Honda Civic Toyota Corolla
Fiat 500 1 0 0 0 0 0
Peugeot 309 1 1 1 1 1 1
Renault Clio 1 0 1 1 1 1
Opel Astra 1 0 0 1 0 1
Honda Civic 1 0 1 1 1 1
Toyota Corolla 1 0 0 1 0 1
[69]:
preference_matrices[2].data
[69]:
Fiat 500 Peugeot 309 Renault Clio Opel Astra Honda Civic Toyota Corolla
Fiat 500 1 0 1 1 1 1
Peugeot 309 1 1 1 1 1 1
Renault Clio 0 0 1 1 1 1
Opel Astra 0 0 1 1 1 1
Honda Civic 0 0 0 0 1 0
Toyota Corolla 0 0 1 1 1 1

Ranking

[70]:
rank = srmp.exploit(
    preference_matrices,
)
rank.data
[70]:
Fiat 500          2
Peugeot 309       1
Renault Clio      3
Opel Astra        5
Honda Civic       6
Toyota Corolla    4
dtype: int64
[71]:
PreferenceStructure.from_ranking(rank).plot()
[71]:
../../_images/notebooks_examples_outranking_algorithms_109_0.svg

Direct method

[72]:
rank = srmp.rank()
rank.data
[72]:
Fiat 500          2
Peugeot 309       1
Renault Clio      3
Opel Astra        5
Honda Civic       6
Toyota Corolla    4
dtype: int64
[73]:
PreferenceStructure.from_ranking(rank).plot()
[73]:
../../_images/notebooks_examples_outranking_algorithms_112_0.svg

Plot

Input data

[74]:
SRMP.plot_input_data(
    performance_table,
    srmp,
    xticklabels_tilted=False,
    annotations=True,
    scales_boundaries=False, # better readibility
    annotations_alpha=0.5,
    figsize=(10, 8),
)

Comparison between alternatives

[75]:
SRMP.plot_input_data(
    PerformanceTable(
        performance_table.data.loc[["Fiat 500", "Renault Clio"]],
        scales=scales
    ),
    srmp,
    xticklabels_tilted=False,
    annotations=False,
    scales_boundaries=True, # to keep the same boundaries between the comparisons
)
[76]:
SRMP.plot_input_data(
    PerformanceTable(
        performance_table.data.loc[["Opel Astra", "Toyota Corolla"]],
        scales=scales
    ),
    srmp,
    xticklabels_tilted=False,
    annotations=False,
    scales_boundaries=True, # to keep the same boundaries between the comparisons
)

Concordance

[77]:
srmp.plot_concordance_index(
    performance_table,
    figsize=(10, 4),
    nrows=1,
    xlabels_tilted=False,
)

Progressive ranking

[78]:
srmp.plot_progressive_ranking(
    performance_table
)

SRMP Training

Providing relations

[79]:
from mcda.relations import *

relations = PreferenceStructure([
    P("Fiat 500", "Honda Civic"),
    P("Toyota Corolla", "Opel Astra"),
    P("Fiat 500", "Renault Clio"),
    P("Honda Civic", "Toyota Corolla"),
    I("Opel Astra", "Peugeot 309"),
    I("Renault Clio", "Honda Civic"),
])
relations.plot()
[79]:
../../_images/notebooks_examples_outranking_algorithms_123_0.svg

Train a SRMP model

[80]:
learner = SRMPLearner(
    performance_table,
    relations,
    max_profiles_number=3,
    non_dictator=True,
    gamma=0.01
)
srmp = learner.learn()
srmp.__dict__, learner.fitness
Welcome to the CBC MILP Solver
Version: 2.10.3
Build Date: Dec 15 2019

command line - /home/nduminy/.pyenv/versions/3.10.7/envs/pymcda-test/lib/python3.10/site-packages/pulp/solverdir/cbc/linux/64/cbc /tmp/ce71c2ac984643faae879ad412e8d792-pulp.mps max timeMode elapsed branch printingOptions all solution /tmp/ce71c2ac984643faae879ad412e8d792-pulp.sol (default strategy 1)
At line 2 NAME          MODEL
At line 3 ROWS
At line 226 COLUMNS
At line 890 RHS
At line 1112 BOUNDS
At line 1193 ENDATA
Problem MODEL has 221 rows, 80 columns and 577 elements
Coin0008I MODEL read with 0 errors
Option for timeMode changed from cpu to elapsed
Continuous objective value is 6 - 0.00 seconds
Cgl0002I 4 variables fixed
Cgl0003I 0 fixed, 0 tightened bounds, 113 strengthened rows, 6 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 18 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 7 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 3 strengthened rows, 0 substitutions
Cgl0004I processed model has 127 rows, 59 columns (25 integer (25 of which binary)) and 472 elements
Cbc0045I 4 integer variables out of 25 objects (25 integer) have cost of -1 - high priority
Cbc0045I branch on satisfied Y create fake objective Y random cost Y
Cbc0038I Initial state - 4 integers unsatisfied sum - 0.958776
Cbc0038I Pass   1: suminf.    0.08000 (4) obj. -5.98 iterations 14
Cbc0038I Pass   2: suminf.    0.20381 (2) obj. -4 iterations 23
Cbc0038I Pass   3: suminf.    0.06000 (2) obj. -4 iterations 10
Cbc0038I Pass   4: suminf.    0.91803 (6) obj. -4 iterations 35
Cbc0038I Pass   5: suminf.    0.36485 (3) obj. -4 iterations 3
Cbc0038I Pass   6: suminf.    0.01000 (1) obj. -4 iterations 10
Cbc0038I Pass   7: suminf.    0.00000 (0) obj. -4 iterations 3
Cbc0038I Solution found of -4
Cbc0038I Relaxing continuous gives -4
Cbc0038I Rounding solution of -5 is better than previous of -4

Cbc0038I Before mini branch and bound, 10 integers at bound fixed and 11 continuous
Cbc0038I Full problem 127 rows 59 columns, reduced to 58 rows 27 columns
Cbc0038I Mini branch and bound did not improve solution (0.01 seconds)
Cbc0038I Round again with cutoff of -5.99991
Cbc0038I Reduced cost fixing fixed 4 variables on major pass 2
Cbc0038I Pass   8: suminf.    0.16000 (4) obj. -6 iterations 5
Cbc0038I Pass   9: suminf.    0.46315 (3) obj. -6 iterations 18
Cbc0038I Pass  10: suminf.    0.30648 (2) obj. -6 iterations 8
Cbc0038I Pass  11: suminf.    0.03000 (2) obj. -6 iterations 6
Cbc0038I Pass  12: suminf.    0.43841 (5) obj. -6 iterations 17
Cbc0038I Pass  13: suminf.    0.04000 (3) obj. -6 iterations 12
Cbc0038I Pass  14: suminf.    1.38975 (9) obj. -6 iterations 35
Cbc0038I Pass  15: suminf.    1.35918 (7) obj. -6 iterations 7
Cbc0038I Pass  16: suminf.    0.60674 (5) obj. -6 iterations 7
Cbc0038I Pass  17: suminf.    0.13857 (1) obj. -6 iterations 13
Cbc0038I Pass  18: suminf.    0.02000 (1) obj. -6 iterations 3
Cbc0038I Pass  19: suminf.    0.68582 (6) obj. -6 iterations 7
Cbc0038I Pass  20: suminf.    0.53390 (3) obj. -6 iterations 2
Cbc0038I Pass  21: suminf.    0.73907 (6) obj. -6 iterations 12
Cbc0038I Pass  22: suminf.    0.56469 (4) obj. -6 iterations 5
Cbc0038I Pass  23: suminf.    0.49688 (3) obj. -6 iterations 13
Cbc0038I Pass  24: suminf.    0.16908 (3) obj. -6 iterations 1
Cbc0038I Pass  25: suminf.    0.07000 (3) obj. -6 iterations 9
Cbc0038I Pass  26: suminf.    0.66478 (4) obj. -6 iterations 13
Cbc0038I Pass  27: suminf.    0.33698 (4) obj. -6 iterations 3
Cbc0038I Pass  28: suminf.    2.28686 (8) obj. -6 iterations 29
Cbc0038I Pass  29: suminf.    1.34367 (5) obj. -6 iterations 13
Cbc0038I Pass  30: suminf.    0.39000 (4) obj. -6 iterations 9
Cbc0038I Pass  31: suminf.    0.13857 (1) obj. -6 iterations 11
Cbc0038I Pass  32: suminf.    0.02000 (1) obj. -6 iterations 4
Cbc0038I Pass  33: suminf.    0.97045 (7) obj. -6 iterations 10
Cbc0038I Pass  34: suminf.    0.60173 (4) obj. -6 iterations 2
Cbc0038I Pass  35: suminf.    0.30648 (2) obj. -6 iterations 6
Cbc0038I Pass  36: suminf.    0.96064 (5) obj. -6 iterations 24
Cbc0038I Pass  37: suminf.    0.18667 (3) obj. -6 iterations 15
Cbc0038I Pass  38: suminf.    0.27632 (1) obj. -6 iterations 7
Cbc0038I Pass  39: suminf.    0.01000 (1) obj. -6 iterations 5
Cbc0038I Pass  40: suminf.    2.09487 (12) obj. -6 iterations 37
Cbc0038I Pass  41: suminf.    1.18860 (7) obj. -6 iterations 18
Cbc0038I Pass  42: suminf.    1.11659 (4) obj. -6 iterations 31
Cbc0038I Pass  43: suminf.    0.26000 (3) obj. -6 iterations 14
Cbc0038I Pass  44: suminf.    0.40422 (2) obj. -6 iterations 6
Cbc0038I Pass  45: suminf.    0.17000 (1) obj. -6 iterations 7
Cbc0038I Pass  46: suminf.    0.27632 (1) obj. -6 iterations 2
Cbc0038I Pass  47: suminf.    2.05510 (8) obj. -6 iterations 24
Cbc0038I Pass  48: suminf.    1.59626 (7) obj. -6 iterations 3
Cbc0038I Pass  49: suminf.    0.57000 (5) obj. -6 iterations 27
Cbc0038I Pass  50: suminf.    0.08000 (4) obj. -6 iterations 2
Cbc0038I Pass  51: suminf.    0.66478 (4) obj. -6 iterations 18
Cbc0038I Pass  52: suminf.    0.33698 (4) obj. -6 iterations 3
Cbc0038I Pass  53: suminf.    0.07000 (3) obj. -6 iterations 9
Cbc0038I Pass  54: suminf.    0.63649 (4) obj. -6 iterations 19
Cbc0038I Pass  55: suminf.    0.07000 (3) obj. -6 iterations 11
Cbc0038I Pass  56: suminf.    0.66478 (4) obj. -6 iterations 14
Cbc0038I Pass  57: suminf.    0.33698 (4) obj. -6 iterations 1
Cbc0038I Pass  58: suminf.    0.72976 (5) obj. -6 iterations 16
Cbc0038I Pass  59: suminf.    0.40263 (6) obj. -6 iterations 5
Cbc0038I Pass  60: suminf.    1.59892 (7) obj. -6 iterations 6
Cbc0038I Pass  61: suminf.    1.59165 (7) obj. -6 iterations 2
Cbc0038I Pass  62: suminf.    0.02000 (1) obj. -6 iterations 13
Cbc0038I Pass  63: suminf.    0.13857 (1) obj. -6 iterations 4
Cbc0038I Pass  64: suminf.    0.59062 (3) obj. -6 iterations 21
Cbc0038I Pass  65: suminf.    0.19667 (3) obj. -6 iterations 10
Cbc0038I Pass  66: suminf.    0.13857 (1) obj. -6 iterations 6
Cbc0038I Pass  67: suminf.    0.02000 (1) obj. -6 iterations 1
Cbc0038I Pass  68: suminf.    0.44460 (6) obj. -6 iterations 14
Cbc0038I Pass  69: suminf.    0.14791 (2) obj. -6 iterations 5
Cbc0038I Pass  70: suminf.    0.46236 (2) obj. -6 iterations 11
Cbc0038I Pass  71: suminf.    0.46236 (2) obj. -6 iterations 0
Cbc0038I Pass  72: suminf.    0.01000 (1) obj. -6 iterations 7
Cbc0038I Pass  73: suminf.    0.27632 (1) obj. -6 iterations 2
Cbc0038I Pass  74: suminf.    0.37000 (2) obj. -6 iterations 16
Cbc0038I Pass  75: suminf.    0.37000 (2) obj. -6 iterations 0
Cbc0038I Pass  76: suminf.    0.13857 (1) obj. -6 iterations 3
Cbc0038I Pass  77: suminf.    0.02000 (1) obj. -6 iterations 1
Cbc0038I Pass  78: suminf.    0.83059 (7) obj. -6 iterations 16
Cbc0038I Pass  79: suminf.    0.53390 (3) obj. -6 iterations 6
Cbc0038I Pass  80: suminf.    1.33503 (6) obj. -6 iterations 19
Cbc0038I Pass  81: suminf.    0.58484 (5) obj. -6 iterations 7
Cbc0038I Pass  82: suminf.    0.59389 (3) obj. -6 iterations 18
Cbc0038I Pass  83: suminf.    0.15382 (3) obj. -6 iterations 5
Cbc0038I Pass  84: suminf.    0.06000 (4) obj. -6 iterations 11
Cbc0038I Pass  85: suminf.    0.66478 (4) obj. -6 iterations 17
Cbc0038I Pass  86: suminf.    0.32173 (4) obj. -6 iterations 2
Cbc0038I Pass  87: suminf.    0.05000 (3) obj. -6 iterations 12
Cbc0038I Pass  88: suminf.    0.58721 (5) obj. -6 iterations 6
Cbc0038I Pass  89: suminf.    0.09530 (6) obj. -6 iterations 3
Cbc0038I Pass  90: suminf.    0.50621 (4) obj. -6 iterations 18
Cbc0038I Pass  91: suminf.    0.16434 (4) obj. -6 iterations 3
Cbc0038I Pass  92: suminf.    0.21634 (4) obj. -6 iterations 9
Cbc0038I Pass  93: suminf.    0.20862 (4) obj. -6 iterations 5
Cbc0038I Pass  94: suminf.    0.05000 (3) obj. -6 iterations 10
Cbc0038I Pass  95: suminf.    0.66478 (4) obj. -6 iterations 7
Cbc0038I Pass  96: suminf.    0.32173 (4) obj. -6 iterations 1
Cbc0038I Pass  97: suminf.    0.60279 (4) obj. -6 iterations 11
Cbc0038I Pass  98: suminf.    0.01000 (1) obj. -6 iterations 9
Cbc0038I Pass  99: suminf.    0.27632 (1) obj. -6 iterations 2
Cbc0038I Pass 100: suminf.    0.50915 (6) obj. -6 iterations 25
Cbc0038I Pass 101: suminf.    0.03000 (2) obj. -6 iterations 6
Cbc0038I Pass 102: suminf.    0.30648 (2) obj. -6 iterations 4
Cbc0038I Pass 103: suminf.    0.31648 (3) obj. -6 iterations 4
Cbc0038I Pass 104: suminf.    1.07677 (4) obj. -6 iterations 13
Cbc0038I Pass 105: suminf.    0.61862 (4) obj. -6 iterations 5
Cbc0038I Pass 106: suminf.    0.47047 (5) obj. -6 iterations 12
Cbc0038I Pass 107: suminf.    1.75610 (10) obj. -6 iterations 24
Cbc0038I No solution found this major pass
Cbc0038I Before mini branch and bound, 4 integers at bound fixed and 1 continuous
Cbc0038I Full problem 127 rows 59 columns, reduced to 125 rows 54 columns - 3 fixed gives 120, 51 - ok now
Cbc0038I Full problem 127 rows 59 columns, reduced to 102 rows 45 columns
Cbc0038I Mini branch and bound did not improve solution (0.06 seconds)
Cbc0038I After 0.06 seconds - Feasibility pump exiting with objective of -5 - took 0.05 seconds
Cbc0012I Integer solution of -5 found by feasibility pump after 0 iterations and 0 nodes (0.06 seconds)
Cbc0031I 33 added rows had average density of 15.666667
Cbc0013I At root node, 33 cuts changed objective from -6 to -6 in 100 passes
Cbc0014I Cut generator 0 (Probing) - 1342 row cuts average 2.9 elements, 0 column cuts (0 active)  in 0.026 seconds - new frequency is -100
Cbc0014I Cut generator 1 (Gomory) - 735 row cuts average 48.9 elements, 0 column cuts (0 active)  in 0.015 seconds - new frequency is -100
Cbc0014I Cut generator 2 (Knapsack) - 50 row cuts average 4.4 elements, 0 column cuts (0 active)  in 0.016 seconds - new frequency is -100
Cbc0014I Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.001 seconds - new frequency is -100
Cbc0014I Cut generator 4 (MixedIntegerRounding2) - 276 row cuts average 4.1 elements, 0 column cuts (0 active)  in 0.015 seconds - new frequency is -100
Cbc0014I Cut generator 5 (FlowCover) - 20 row cuts average 2.9 elements, 0 column cuts (0 active)  in 0.015 seconds - new frequency is -100
Cbc0014I Cut generator 6 (TwoMirCuts) - 236 row cuts average 5.0 elements, 0 column cuts (0 active)  in 0.007 seconds - new frequency is -100
Cbc0010I After 0 nodes, 1 on tree, -5 best solution, best possible -6 (0.24 seconds)
Cbc0001I Search completed - best objective -5, took 2531 iterations and 6 nodes (0.26 seconds)
Cbc0032I Strong branching done 52 times (521 iterations), fathomed 4 nodes and fixed 0 variables
Cbc0035I Maximum depth 2, 4 variables fixed on reduced cost
Cuts at root node changed objective from -6 to -6
Probing was tried 100 times and created 1342 cuts of which 0 were active after adding rounds of cuts (0.026 seconds)
Gomory was tried 100 times and created 735 cuts of which 0 were active after adding rounds of cuts (0.015 seconds)
Knapsack was tried 100 times and created 50 cuts of which 0 were active after adding rounds of cuts (0.016 seconds)
Clique was tried 100 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.001 seconds)
MixedIntegerRounding2 was tried 100 times and created 276 cuts of which 0 were active after adding rounds of cuts (0.015 seconds)
FlowCover was tried 100 times and created 20 cuts of which 0 were active after adding rounds of cuts (0.015 seconds)
TwoMirCuts was tried 100 times and created 236 cuts of which 0 were active after adding rounds of cuts (0.007 seconds)
ZeroHalf was tried 1 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
ImplicationCuts was tried 12 times and created 74 cuts of which 0 were active after adding rounds of cuts (0.001 seconds)

Result - Optimal solution found

Objective value:                5.00000000
Enumerated nodes:               6
Total iterations:               2531
Time (CPU seconds):             0.25
Time (Wallclock seconds):       0.26

Option for printingOptions changed from normal to all
Total time (CPU seconds):       0.25   (Wallclock seconds):       0.26

Welcome to the CBC MILP Solver
Version: 2.10.3
Build Date: Dec 15 2019

command line - /home/nduminy/.pyenv/versions/3.10.7/envs/pymcda-test/lib/python3.10/site-packages/pulp/solverdir/cbc/linux/64/cbc /tmp/a0f05c0bd2c743ac9129206ce2ee0ea7-pulp.mps max timeMode elapsed branch printingOptions all solution /tmp/a0f05c0bd2c743ac9129206ce2ee0ea7-pulp.sol (default strategy 1)
At line 2 NAME          MODEL
At line 3 ROWS
At line 427 COLUMNS
At line 1717 RHS
At line 2140 BOUNDS
At line 2290 ENDATA
Problem MODEL has 422 rows, 149 columns and 1135 elements
Coin0008I MODEL read with 0 errors
Option for timeMode changed from cpu to elapsed
Continuous objective value is 6 - 0.00 seconds
Cgl0002I 4 variables fixed
Cgl0003I 0 fixed, 0 tightened bounds, 234 strengthened rows, 12 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 50 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 24 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 6 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 1 strengthened rows, 0 substitutions
Cgl0004I processed model has 265 rows, 113 columns (50 integer (50 of which binary)) and 1021 elements
Cbc0045I 4 integer variables out of 50 objects (50 integer) have cost of -1 - high priority
Cbc0045I branch on satisfied Y create fake objective Y random cost Y
Cbc0038I Initial state - 9 integers unsatisfied sum - 2.54009
Cbc0038I Pass   1: suminf.    0.13950 (8) obj. -6 iterations 56
Cbc0038I Pass   2: suminf.    0.66817 (7) obj. -5.93298 iterations 41
Cbc0038I Pass   3: suminf.    0.54000 (5) obj. -5.98 iterations 13
Cbc0038I Pass   4: suminf.    0.57850 (5) obj. -5 iterations 21
Cbc0038I Pass   5: suminf.    0.52495 (4) obj. -5 iterations 8
Cbc0038I Pass   6: suminf.    0.57709 (5) obj. -5 iterations 23
Cbc0038I Pass   7: suminf.    0.52000 (4) obj. -5 iterations 14
Cbc0038I Pass   8: suminf.    2.67583 (14) obj. -5 iterations 73
Cbc0038I Pass   9: suminf.    1.13367 (6) obj. -5 iterations 20
Cbc0038I Pass  10: suminf.    0.02980 (2) obj. -5 iterations 19
Cbc0038I Pass  11: suminf.    0.01990 (2) obj. -5 iterations 10
Cbc0038I Pass  12: suminf.    2.23988 (11) obj. -5 iterations 40
Cbc0038I Pass  13: suminf.    0.52480 (5) obj. -5 iterations 45
Cbc0038I Pass  14: suminf.    0.02000 (2) obj. -5 iterations 13
Cbc0038I Pass  15: suminf.    0.01980 (2) obj. -5 iterations 5
Cbc0038I Pass  16: suminf.    1.21119 (10) obj. -5 iterations 38
Cbc0038I Pass  17: suminf.    0.69357 (7) obj. -5 iterations 13
Cbc0038I Pass  18: suminf.    0.17906 (2) obj. -5 iterations 21
Cbc0038I Pass  19: suminf.    0.27105 (2) obj. -5 iterations 6
Cbc0038I Pass  20: suminf.    4.25933 (19) obj. -4 iterations 78
Cbc0038I Pass  21: suminf.    2.08028 (15) obj. -4 iterations 17
Cbc0038I Pass  22: suminf.    1.30050 (13) obj. -4 iterations 5
Cbc0038I Pass  23: suminf.    0.52139 (5) obj. -4 iterations 45
Cbc0038I Pass  24: suminf.    0.27000 (3) obj. -4 iterations 22
Cbc0038I Pass  25: suminf.    0.01980 (1) obj. -4 iterations 11
Cbc0038I Pass  26: suminf.    0.02000 (1) obj. -4 iterations 1
Cbc0038I Pass  27: suminf.    1.63179 (7) obj. -4 iterations 28
Cbc0038I Pass  28: suminf.    0.90755 (6) obj. -4 iterations 8
Cbc0038I Pass  29: suminf.    0.20162 (3) obj. -4 iterations 16
Cbc0038I Pass  30: suminf.    0.02000 (1) obj. -4 iterations 13
Cbc0038I Pass  31: suminf.    0.01980 (1) obj. -4 iterations 3
Cbc0038I Pass  32: suminf.    0.51648 (3) obj. -5 iterations 25
Cbc0038I Pass  33: suminf.    0.51648 (3) obj. -5 iterations 3
Cbc0038I Pass  34: suminf.    0.18162 (2) obj. -5 iterations 16
Cbc0038I Pass  35: suminf.    0.09080 (4) obj. -4.99 iterations 16
Cbc0038I Pass  36: suminf.    0.02980 (2) obj. -4 iterations 17
Cbc0038I Pass  37: suminf.    0.02000 (1) obj. -4 iterations 5
Cbc0038I Pass  38: suminf.    0.01980 (1) obj. -4 iterations 3
Cbc0038I Pass  39: suminf.    3.00913 (12) obj. -4 iterations 59
Cbc0038I Pass  40: suminf.    1.48897 (7) obj. -4 iterations 12
Cbc0038I Pass  41: suminf.    0.14437 (2) obj. -4 iterations 29
Cbc0038I Pass  42: suminf.    0.25743 (1) obj. -4 iterations 9
Cbc0038I Pass  43: suminf.    0.25000 (1) obj. -4 iterations 1
Cbc0038I Pass  44: suminf.    0.43667 (4) obj. -4 iterations 30
Cbc0038I Pass  45: suminf.    0.12333 (4) obj. -4 iterations 4
Cbc0038I Pass  46: suminf.    0.00000 (0) obj. -4 iterations 11
Cbc0038I Solution found of -4
Cbc0038I Relaxing continuous gives -4
Cbc0038I Rounding solution of -5 is better than previous of -4

Cbc0038I Before mini branch and bound, 3 integers at bound fixed and 6 continuous
Cbc0038I Full problem 265 rows 113 columns, reduced to 250 rows 104 columns - 1 fixed gives 249, 103 - still too large
Cbc0038I Mini branch and bound did not improve solution (0.04 seconds)
Cbc0038I Round again with cutoff of -5.99991
Cbc0038I Reduced cost fixing fixed 4 variables on major pass 2
Cbc0038I Pass  47: suminf.    0.13950 (8) obj. -6 iterations 0
Cbc0038I Pass  48: suminf.    0.66750 (7) obj. -6 iterations 59
Cbc0038I Pass  49: suminf.    0.53980 (5) obj. -6 iterations 11
Cbc0038I Pass  50: suminf.    0.74221 (7) obj. -6 iterations 24
Cbc0038I Pass  51: suminf.    0.54495 (5) obj. -6 iterations 12
Cbc0038I Pass  52: suminf.    0.74988 (6) obj. -6 iterations 22
Cbc0038I Pass  53: suminf.    1.16678 (13) obj. -6 iterations 63
Cbc0038I Pass  54: suminf.    0.92229 (9) obj. -6 iterations 17
Cbc0038I Pass  55: suminf.    0.75060 (5) obj. -6 iterations 51
Cbc0038I Pass  56: suminf.    0.17657 (2) obj. -6 iterations 7
Cbc0038I Pass  57: suminf.    0.12000 (2) obj. -6 iterations 9
Cbc0038I Pass  58: suminf.    0.02990 (2) obj. -6 iterations 5
Cbc0038I Pass  59: suminf.    1.03190 (4) obj. -6 iterations 29
Cbc0038I Pass  60: suminf.    0.06000 (3) obj. -6 iterations 20
Cbc0038I Pass  61: suminf.    0.11990 (2) obj. -6 iterations 8
Cbc0038I Pass  62: suminf.    0.05000 (2) obj. -6 iterations 6
Cbc0038I Pass  63: suminf.    2.25388 (13) obj. -6 iterations 32
Cbc0038I Pass  64: suminf.    0.60166 (9) obj. -6 iterations 21
Cbc0038I Pass  65: suminf.    0.59319 (8) obj. -6 iterations 6
Cbc0038I Pass  66: suminf.    0.54318 (3) obj. -6 iterations 21
Cbc0038I Pass  67: suminf.    0.12280 (3) obj. -6 iterations 12
Cbc0038I Pass  68: suminf.    0.22868 (3) obj. -6 iterations 12
Cbc0038I Pass  69: suminf.    0.19990 (3) obj. -6 iterations 22
Cbc0038I Pass  70: suminf.    0.12000 (2) obj. -6 iterations 11
Cbc0038I Pass  71: suminf.    0.02990 (2) obj. -6 iterations 5
Cbc0038I Pass  72: suminf.    2.33034 (11) obj. -6 iterations 52
Cbc0038I Pass  73: suminf.    0.85947 (7) obj. -6 iterations 8
Cbc0038I Pass  74: suminf.    0.78907 (9) obj. -6 iterations 9
Cbc0038I Pass  75: suminf.    0.54000 (7) obj. -6 iterations 28
Cbc0038I Pass  76: suminf.    0.80487 (5) obj. -6 iterations 14
Cbc0038I Pass  77: suminf.    0.14000 (3) obj. -6 iterations 17
Cbc0038I Pass  78: suminf.    0.21323 (3) obj. -6 iterations 14
Cbc0038I Pass  79: suminf.    0.03000 (2) obj. -6 iterations 10
Cbc0038I Pass  80: suminf.    0.11990 (2) obj. -6 iterations 5
Cbc0038I Pass  81: suminf.    0.44349 (5) obj. -6 iterations 34
Cbc0038I Pass  82: suminf.    0.39254 (3) obj. -6 iterations 5
Cbc0038I Pass  83: suminf.    0.02000 (2) obj. -6 iterations 15
Cbc0038I Pass  84: suminf.    0.58387 (3) obj. -6 iterations 10
Cbc0038I Pass  85: suminf.    0.03000 (3) obj. -6 iterations 11
Cbc0038I Pass  86: suminf.    0.21603 (4) obj. -6 iterations 14
Cbc0038I Pass  87: suminf.    0.37000 (3) obj. -6 iterations 15
Cbc0038I Pass  88: suminf.    0.12270 (3) obj. -6 iterations 11
Cbc0038I Pass  89: suminf.    1.94595 (12) obj. -6 iterations 46
Cbc0038I Pass  90: suminf.    0.55192 (6) obj. -6 iterations 13
Cbc0038I Pass  91: suminf.    0.65812 (7) obj. -6 iterations 28
Cbc0038I Pass  92: suminf.    0.14380 (5) obj. -6 iterations 9
Cbc0038I Pass  93: suminf.    0.11990 (2) obj. -6 iterations 14
Cbc0038I Pass  94: suminf.    0.03000 (2) obj. -6 iterations 4
Cbc0038I Pass  95: suminf.    2.16973 (10) obj. -6 iterations 34
Cbc0038I Pass  96: suminf.    1.45646 (9) obj. -6 iterations 7
Cbc0038I Pass  97: suminf.    1.33310 (9) obj. -6 iterations 41
Cbc0038I Pass  98: suminf.    0.15990 (3) obj. -6 iterations 29
Cbc0038I Pass  99: suminf.    0.11990 (2) obj. -6 iterations 4
Cbc0038I Pass 100: suminf.    0.03000 (2) obj. -6 iterations 4
Cbc0038I Pass 101: suminf.    1.11914 (7) obj. -6 iterations 26
Cbc0038I Pass 102: suminf.    0.62865 (4) obj. -6 iterations 7
Cbc0038I Pass 103: suminf.    0.11990 (2) obj. -6 iterations 9
Cbc0038I Pass 104: suminf.    0.05000 (2) obj. -6 iterations 14
Cbc0038I Pass 105: suminf.    1.03752 (16) obj. -6 iterations 49
Cbc0038I Pass 106: suminf.    0.82513 (9) obj. -6 iterations 14
Cbc0038I Pass 107: suminf.    0.17990 (2) obj. -6 iterations 30
Cbc0038I Pass 108: suminf.    0.12000 (2) obj. -6 iterations 7
Cbc0038I Pass 109: suminf.    0.02990 (2) obj. -6 iterations 8
Cbc0038I Pass 110: suminf.    2.12656 (11) obj. -6 iterations 30
Cbc0038I Pass 111: suminf.    0.37280 (7) obj. -6 iterations 19
Cbc0038I Pass 112: suminf.    0.57140 (6) obj. -6 iterations 33
Cbc0038I Pass 113: suminf.    0.11990 (2) obj. -6 iterations 18
Cbc0038I Pass 114: suminf.    0.03000 (2) obj. -6 iterations 7
Cbc0038I Pass 115: suminf.    3.50534 (14) obj. -6 iterations 54
Cbc0038I Pass 116: suminf.    1.34126 (11) obj. -6 iterations 16
Cbc0038I Pass 117: suminf.    0.84102 (11) obj. -6 iterations 15
Cbc0038I Pass 118: suminf.    0.24080 (3) obj. -6 iterations 23
Cbc0038I Pass 119: suminf.    0.01000 (1) obj. -6 iterations 10
Cbc0038I Pass 120: suminf.    0.01980 (1) obj. -6 iterations 2
Cbc0038I Pass 121: suminf.    0.80815 (8) obj. -6 iterations 32
Cbc0038I Pass 122: suminf.    0.80815 (8) obj. -6 iterations 0
Cbc0038I Pass 123: suminf.    0.62541 (5) obj. -6 iterations 24
Cbc0038I Pass 124: suminf.    0.36822 (3) obj. -6 iterations 27
Cbc0038I Pass 125: suminf.    0.28000 (2) obj. -6 iterations 14
Cbc0038I Pass 126: suminf.    0.19822 (2) obj. -6 iterations 13
Cbc0038I Pass 127: suminf.    4.43043 (19) obj. -6 iterations 72
Cbc0038I Pass 128: suminf.    2.33130 (14) obj. -6 iterations 14
Cbc0038I Pass 129: suminf.    1.93209 (14) obj. -6 iterations 5
Cbc0038I Pass 130: suminf.    1.30290 (11) obj. -6 iterations 5
Cbc0038I Pass 131: suminf.    0.40816 (5) obj. -6 iterations 48
Cbc0038I Pass 132: suminf.    0.20000 (6) obj. -6 iterations 8
Cbc0038I Pass 133: suminf.    0.29579 (3) obj. -6 iterations 19
Cbc0038I Pass 134: suminf.    0.03990 (3) obj. -6 iterations 6
Cbc0038I Pass 135: suminf.    0.38316 (3) obj. -6 iterations 11
Cbc0038I Pass 136: suminf.    0.13000 (3) obj. -6 iterations 4
Cbc0038I Pass 137: suminf.    0.30147 (4) obj. -6 iterations 31
Cbc0038I Pass 138: suminf.    0.02495 (4) obj. -6 iterations 14
Cbc0038I Pass 139: suminf.    0.34667 (3) obj. -6 iterations 20
Cbc0038I Pass 140: suminf.    0.21000 (1) obj. -6 iterations 6
Cbc0038I Pass 141: suminf.    0.00990 (1) obj. -6 iterations 4
Cbc0038I Pass 142: suminf.    0.01000 (1) obj. -6 iterations 2
Cbc0038I Pass 143: suminf.    1.28147 (10) obj. -6 iterations 38
Cbc0038I Pass 144: suminf.    1.28147 (10) obj. -6 iterations 2
Cbc0038I Pass 145: suminf.    0.20137 (4) obj. -6 iterations 29
Cbc0038I Pass 146: suminf.    1.57224 (8) obj. -6 iterations 35
Cbc0038I No solution found this major pass
Cbc0038I Before mini branch and bound, 6 integers at bound fixed and 4 continuous
Cbc0038I Full problem 265 rows 113 columns, reduced to 255 rows 103 columns - 3 fixed gives 246, 100 - still too large
Cbc0038I Mini branch and bound did not improve solution (0.11 seconds)
Cbc0038I After 0.11 seconds - Feasibility pump exiting with objective of -5 - took 0.09 seconds
Cbc0012I Integer solution of -5 found by feasibility pump after 0 iterations and 0 nodes (0.11 seconds)
Cbc0038I Full problem 265 rows 113 columns, reduced to 116 rows 46 columns
Cbc0031I 41 added rows had average density of 17.609756
Cbc0013I At root node, 41 cuts changed objective from -6 to -6 in 13 passes
Cbc0014I Cut generator 0 (Probing) - 229 row cuts average 6.3 elements, 0 column cuts (0 active)  in 0.006 seconds - new frequency is -100
Cbc0014I Cut generator 1 (Gomory) - 70 row cuts average 58.8 elements, 0 column cuts (0 active)  in 0.003 seconds - new frequency is -100
Cbc0014I Cut generator 2 (Knapsack) - 14 row cuts average 5.7 elements, 0 column cuts (0 active)  in 0.003 seconds - new frequency is -100
Cbc0014I Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 4 (MixedIntegerRounding2) - 71 row cuts average 11.4 elements, 0 column cuts (0 active)  in 0.003 seconds - new frequency is -100
Cbc0014I Cut generator 5 (FlowCover) - 1 row cuts average 2.0 elements, 0 column cuts (0 active)  in 0.002 seconds - new frequency is -100
Cbc0014I Cut generator 6 (TwoMirCuts) - 76 row cuts average 38.4 elements, 0 column cuts (0 active)  in 0.002 seconds - new frequency is -100
Cbc0010I After 0 nodes, 1 on tree, -5 best solution, best possible -6 (0.16 seconds)
Cbc0038I Full problem 265 rows 113 columns, reduced to 100 rows 41 columns
Cbc0038I Full problem 265 rows 113 columns, reduced to 91 rows 37 columns
Cbc0038I Full problem 265 rows 113 columns, reduced to 95 rows 40 columns
Cbc0012I Integer solution of -6 found by DiveCoefficient after 9892 iterations and 290 nodes (0.63 seconds)
Cbc0001I Search completed - best objective -6, took 9892 iterations and 290 nodes (0.63 seconds)
Cbc0032I Strong branching done 2074 times (23738 iterations), fathomed 123 nodes and fixed 46 variables
Cbc0035I Maximum depth 13, 4 variables fixed on reduced cost
Cuts at root node changed objective from -6 to -6
Probing was tried 13 times and created 229 cuts of which 0 were active after adding rounds of cuts (0.006 seconds)
Gomory was tried 13 times and created 70 cuts of which 0 were active after adding rounds of cuts (0.003 seconds)
Knapsack was tried 13 times and created 14 cuts of which 0 were active after adding rounds of cuts (0.003 seconds)
Clique was tried 13 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 13 times and created 71 cuts of which 0 were active after adding rounds of cuts (0.003 seconds)
FlowCover was tried 13 times and created 1 cuts of which 0 were active after adding rounds of cuts (0.002 seconds)
TwoMirCuts was tried 13 times and created 76 cuts of which 0 were active after adding rounds of cuts (0.002 seconds)
ZeroHalf was tried 1 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
ImplicationCuts was tried 33 times and created 284 cuts of which 0 were active after adding rounds of cuts (0.001 seconds)

Result - Optimal solution found

Objective value:                6.00000000
Enumerated nodes:               290
Total iterations:               9892
Time (CPU seconds):             0.63
Time (Wallclock seconds):       0.63

Option for printingOptions changed from normal to all
Total time (CPU seconds):       0.63   (Wallclock seconds):       0.63

[80]:
({'performance_table': <mcda.core.matrices.PerformanceTable at 0x7fa4a9ee0370>,
  'criteria_weights': {'cost': 0.16333333,
   'fuel consumption': 0.16333333,
   'comfort': 0.01,
   'color': 0.16333333,
   'range': 0.5},
  'profiles': <mcda.core.matrices.PerformanceTable at 0x7fa4a726f9a0>,
  'lexicographic_order': [0, 1]},
 1.0)
[81]:
srmp.profiles.data
[81]:
cost fuel consumption comfort color range
0 15460.00006 5.18 *** blue 905.999998
1 6000.00000 4.10 **** red 1000.000000
[82]:
rank = srmp.rank()
rank.data
[82]:
Fiat 500          1
Peugeot 309       4
Renault Clio      2
Opel Astra        4
Honda Civic       2
Toyota Corolla    3
dtype: int64
[83]:
PreferenceStructure.from_ranking(rank).plot()
[83]:
../../_images/notebooks_examples_outranking_algorithms_128_0.svg

You can also directly create and train a SRMP object:

[84]:
srmp = SRMP.learn(
    performance_table,
    relations,
    max_profiles_number=3,
    non_dictator=True,
    gamma=0.01,
)
rank = srmp.rank()
PreferenceStructure.from_ranking(rank).plot()
Welcome to the CBC MILP Solver
Version: 2.10.3
Build Date: Dec 15 2019

command line - /home/nduminy/.pyenv/versions/3.10.7/envs/pymcda-test/lib/python3.10/site-packages/pulp/solverdir/cbc/linux/64/cbc /tmp/e7f9f14165dc48728cecf7a385a493d0-pulp.mps max timeMode elapsed branch printingOptions all solution /tmp/e7f9f14165dc48728cecf7a385a493d0-pulp.sol (default strategy 1)
At line 2 NAME          MODEL
At line 3 ROWS
At line 226 COLUMNS
At line 890 RHS
At line 1112 BOUNDS
At line 1193 ENDATA
Problem MODEL has 221 rows, 80 columns and 577 elements
Coin0008I MODEL read with 0 errors
Option for timeMode changed from cpu to elapsed
Continuous objective value is 6 - 0.00 seconds
Cgl0002I 4 variables fixed
Cgl0003I 0 fixed, 0 tightened bounds, 113 strengthened rows, 6 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 18 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 7 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 3 strengthened rows, 0 substitutions
Cgl0004I processed model has 127 rows, 59 columns (25 integer (25 of which binary)) and 472 elements
Cbc0045I 4 integer variables out of 25 objects (25 integer) have cost of -1 - high priority
Cbc0045I branch on satisfied Y create fake objective Y random cost Y
Cbc0038I Initial state - 4 integers unsatisfied sum - 0.958776
Cbc0038I Pass   1: suminf.    0.08000 (4) obj. -5.98 iterations 14
Cbc0038I Pass   2: suminf.    0.20381 (2) obj. -4 iterations 23
Cbc0038I Pass   3: suminf.    0.06000 (2) obj. -4 iterations 10
Cbc0038I Pass   4: suminf.    0.91803 (6) obj. -4 iterations 35
Cbc0038I Pass   5: suminf.    0.36485 (3) obj. -4 iterations 3
Cbc0038I Pass   6: suminf.    0.01000 (1) obj. -4 iterations 10
Cbc0038I Pass   7: suminf.    0.00000 (0) obj. -4 iterations 3
Cbc0038I Solution found of -4
Cbc0038I Relaxing continuous gives -4
Cbc0038I Rounding solution of -5 is better than previous of -4

Cbc0038I Before mini branch and bound, 10 integers at bound fixed and 11 continuous
Cbc0038I Full problem 127 rows 59 columns, reduced to 58 rows 27 columns
Cbc0038I Mini branch and bound did not improve solution (0.01 seconds)
Cbc0038I Round again with cutoff of -5.99991
Cbc0038I Reduced cost fixing fixed 4 variables on major pass 2
Cbc0038I Pass   8: suminf.    0.16000 (4) obj. -6 iterations 5
Cbc0038I Pass   9: suminf.    0.46315 (3) obj. -6 iterations 18
Cbc0038I Pass  10: suminf.    0.30648 (2) obj. -6 iterations 8
Cbc0038I Pass  11: suminf.    0.03000 (2) obj. -6 iterations 6
Cbc0038I Pass  12: suminf.    0.43841 (5) obj. -6 iterations 17
Cbc0038I Pass  13: suminf.    0.04000 (3) obj. -6 iterations 12
Cbc0038I Pass  14: suminf.    1.38975 (9) obj. -6 iterations 35
Cbc0038I Pass  15: suminf.    1.35918 (7) obj. -6 iterations 7
Cbc0038I Pass  16: suminf.    0.60674 (5) obj. -6 iterations 7
Cbc0038I Pass  17: suminf.    0.13857 (1) obj. -6 iterations 13
Cbc0038I Pass  18: suminf.    0.02000 (1) obj. -6 iterations 3
Cbc0038I Pass  19: suminf.    0.68582 (6) obj. -6 iterations 7
Cbc0038I Pass  20: suminf.    0.53390 (3) obj. -6 iterations 2
Cbc0038I Pass  21: suminf.    0.73907 (6) obj. -6 iterations 12
Cbc0038I Pass  22: suminf.    0.56469 (4) obj. -6 iterations 5
Cbc0038I Pass  23: suminf.    0.49688 (3) obj. -6 iterations 13
Cbc0038I Pass  24: suminf.    0.16908 (3) obj. -6 iterations 1
Cbc0038I Pass  25: suminf.    0.07000 (3) obj. -6 iterations 9
Cbc0038I Pass  26: suminf.    0.66478 (4) obj. -6 iterations 13
Cbc0038I Pass  27: suminf.    0.33698 (4) obj. -6 iterations 3
Cbc0038I Pass  28: suminf.    2.28686 (8) obj. -6 iterations 29
Cbc0038I Pass  29: suminf.    1.34367 (5) obj. -6 iterations 13
Cbc0038I Pass  30: suminf.    0.39000 (4) obj. -6 iterations 9
Cbc0038I Pass  31: suminf.    0.13857 (1) obj. -6 iterations 11
Cbc0038I Pass  32: suminf.    0.02000 (1) obj. -6 iterations 4
Cbc0038I Pass  33: suminf.    0.97045 (7) obj. -6 iterations 10
Cbc0038I Pass  34: suminf.    0.60173 (4) obj. -6 iterations 2
Cbc0038I Pass  35: suminf.    0.30648 (2) obj. -6 iterations 6
Cbc0038I Pass  36: suminf.    0.96064 (5) obj. -6 iterations 24
Cbc0038I Pass  37: suminf.    0.18667 (3) obj. -6 iterations 15
Cbc0038I Pass  38: suminf.    0.27632 (1) obj. -6 iterations 7
Cbc0038I Pass  39: suminf.    0.01000 (1) obj. -6 iterations 5
Cbc0038I Pass  40: suminf.    2.09487 (12) obj. -6 iterations 37
Cbc0038I Pass  41: suminf.    1.18860 (7) obj. -6 iterations 18
Cbc0038I Pass  42: suminf.    1.11659 (4) obj. -6 iterations 31
Cbc0038I Pass  43: suminf.    0.26000 (3) obj. -6 iterations 14
Cbc0038I Pass  44: suminf.    0.40422 (2) obj. -6 iterations 6
Cbc0038I Pass  45: suminf.    0.17000 (1) obj. -6 iterations 7
Cbc0038I Pass  46: suminf.    0.27632 (1) obj. -6 iterations 2
Cbc0038I Pass  47: suminf.    2.05510 (8) obj. -6 iterations 24
Cbc0038I Pass  48: suminf.    1.59626 (7) obj. -6 iterations 3
Cbc0038I Pass  49: suminf.    0.57000 (5) obj. -6 iterations 27
Cbc0038I Pass  50: suminf.    0.08000 (4) obj. -6 iterations 2
Cbc0038I Pass  51: suminf.    0.66478 (4) obj. -6 iterations 18
Cbc0038I Pass  52: suminf.    0.33698 (4) obj. -6 iterations 3
Cbc0038I Pass  53: suminf.    0.07000 (3) obj. -6 iterations 9
Cbc0038I Pass  54: suminf.    0.63649 (4) obj. -6 iterations 19
Cbc0038I Pass  55: suminf.    0.07000 (3) obj. -6 iterations 11
Cbc0038I Pass  56: suminf.    0.66478 (4) obj. -6 iterations 14
Cbc0038I Pass  57: suminf.    0.33698 (4) obj. -6 iterations 1
Cbc0038I Pass  58: suminf.    0.72976 (5) obj. -6 iterations 16
Cbc0038I Pass  59: suminf.    0.40263 (6) obj. -6 iterations 5
Cbc0038I Pass  60: suminf.    1.59892 (7) obj. -6 iterations 6
Cbc0038I Pass  61: suminf.    1.59165 (7) obj. -6 iterations 2
Cbc0038I Pass  62: suminf.    0.02000 (1) obj. -6 iterations 13
Cbc0038I Pass  63: suminf.    0.13857 (1) obj. -6 iterations 4
Cbc0038I Pass  64: suminf.    0.59062 (3) obj. -6 iterations 21
Cbc0038I Pass  65: suminf.    0.19667 (3) obj. -6 iterations 10
Cbc0038I Pass  66: suminf.    0.13857 (1) obj. -6 iterations 6
Cbc0038I Pass  67: suminf.    0.02000 (1) obj. -6 iterations 1
Cbc0038I Pass  68: suminf.    0.44460 (6) obj. -6 iterations 14
Cbc0038I Pass  69: suminf.    0.14791 (2) obj. -6 iterations 5
Cbc0038I Pass  70: suminf.    0.46236 (2) obj. -6 iterations 11
Cbc0038I Pass  71: suminf.    0.46236 (2) obj. -6 iterations 0
Cbc0038I Pass  72: suminf.    0.01000 (1) obj. -6 iterations 7
Cbc0038I Pass  73: suminf.    0.27632 (1) obj. -6 iterations 2
Cbc0038I Pass  74: suminf.    0.37000 (2) obj. -6 iterations 16
Cbc0038I Pass  75: suminf.    0.37000 (2) obj. -6 iterations 0
Cbc0038I Pass  76: suminf.    0.13857 (1) obj. -6 iterations 3
Cbc0038I Pass  77: suminf.    0.02000 (1) obj. -6 iterations 1
Cbc0038I Pass  78: suminf.    0.83059 (7) obj. -6 iterations 16
Cbc0038I Pass  79: suminf.    0.53390 (3) obj. -6 iterations 6
Cbc0038I Pass  80: suminf.    1.33503 (6) obj. -6 iterations 19
Cbc0038I Pass  81: suminf.    0.58484 (5) obj. -6 iterations 7
Cbc0038I Pass  82: suminf.    0.59389 (3) obj. -6 iterations 18
Cbc0038I Pass  83: suminf.    0.15382 (3) obj. -6 iterations 5
Cbc0038I Pass  84: suminf.    0.06000 (4) obj. -6 iterations 11
Cbc0038I Pass  85: suminf.    0.66478 (4) obj. -6 iterations 17
Cbc0038I Pass  86: suminf.    0.32173 (4) obj. -6 iterations 2
Cbc0038I Pass  87: suminf.    0.05000 (3) obj. -6 iterations 12
Cbc0038I Pass  88: suminf.    0.58721 (5) obj. -6 iterations 6
Cbc0038I Pass  89: suminf.    0.09530 (6) obj. -6 iterations 3
Cbc0038I Pass  90: suminf.    0.50621 (4) obj. -6 iterations 18
Cbc0038I Pass  91: suminf.    0.16434 (4) obj. -6 iterations 3
Cbc0038I Pass  92: suminf.    0.21634 (4) obj. -6 iterations 9
Cbc0038I Pass  93: suminf.    0.20862 (4) obj. -6 iterations 5
Cbc0038I Pass  94: suminf.    0.05000 (3) obj. -6 iterations 10
Cbc0038I Pass  95: suminf.    0.66478 (4) obj. -6 iterations 7
Cbc0038I Pass  96: suminf.    0.32173 (4) obj. -6 iterations 1
Cbc0038I Pass  97: suminf.    0.60279 (4) obj. -6 iterations 11
Cbc0038I Pass  98: suminf.    0.01000 (1) obj. -6 iterations 9
Cbc0038I Pass  99: suminf.    0.27632 (1) obj. -6 iterations 2
Cbc0038I Pass 100: suminf.    0.50915 (6) obj. -6 iterations 25
Cbc0038I Pass 101: suminf.    0.03000 (2) obj. -6 iterations 6
Cbc0038I Pass 102: suminf.    0.30648 (2) obj. -6 iterations 4
Cbc0038I Pass 103: suminf.    0.31648 (3) obj. -6 iterations 4
Cbc0038I Pass 104: suminf.    1.07677 (4) obj. -6 iterations 13
Cbc0038I Pass 105: suminf.    0.61862 (4) obj. -6 iterations 5
Cbc0038I Pass 106: suminf.    0.47047 (5) obj. -6 iterations 12
Cbc0038I Pass 107: suminf.    1.75610 (10) obj. -6 iterations 24
Cbc0038I No solution found this major pass
Cbc0038I Before mini branch and bound, 4 integers at bound fixed and 1 continuous
Cbc0038I Full problem 127 rows 59 columns, reduced to 125 rows 54 columns - 3 fixed gives 120, 51 - ok now
Cbc0038I Full problem 127 rows 59 columns, reduced to 102 rows 45 columns
Cbc0038I Mini branch and bound did not improve solution (0.06 seconds)
Cbc0038I After 0.06 seconds - Feasibility pump exiting with objective of -5 - took 0.05 seconds
Cbc0012I Integer solution of -5 found by feasibility pump after 0 iterations and 0 nodes (0.06 seconds)
Cbc0031I 33 added rows had average density of 15.666667
Cbc0013I At root node, 33 cuts changed objective from -6 to -6 in 100 passes
Cbc0014I Cut generator 0 (Probing) - 1342 row cuts average 2.9 elements, 0 column cuts (0 active)  in 0.025 seconds - new frequency is -100
Cbc0014I Cut generator 1 (Gomory) - 735 row cuts average 48.9 elements, 0 column cuts (0 active)  in 0.014 seconds - new frequency is -100
Cbc0014I Cut generator 2 (Knapsack) - 50 row cuts average 4.4 elements, 0 column cuts (0 active)  in 0.016 seconds - new frequency is -100
Cbc0014I Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.001 seconds - new frequency is -100
Cbc0014I Cut generator 4 (MixedIntegerRounding2) - 276 row cuts average 4.1 elements, 0 column cuts (0 active)  in 0.014 seconds - new frequency is -100
Cbc0014I Cut generator 5 (FlowCover) - 20 row cuts average 2.9 elements, 0 column cuts (0 active)  in 0.014 seconds - new frequency is -100
Cbc0014I Cut generator 6 (TwoMirCuts) - 236 row cuts average 5.0 elements, 0 column cuts (0 active)  in 0.007 seconds - new frequency is -100
Cbc0010I After 0 nodes, 1 on tree, -5 best solution, best possible -6 (0.22 seconds)
Cbc0001I Search completed - best objective -5, took 2531 iterations and 6 nodes (0.23 seconds)
Cbc0032I Strong branching done 52 times (521 iterations), fathomed 4 nodes and fixed 0 variables
Cbc0035I Maximum depth 2, 4 variables fixed on reduced cost
Cuts at root node changed objective from -6 to -6
Probing was tried 100 times and created 1342 cuts of which 0 were active after adding rounds of cuts (0.025 seconds)
Gomory was tried 100 times and created 735 cuts of which 0 were active after adding rounds of cuts (0.014 seconds)
Knapsack was tried 100 times and created 50 cuts of which 0 were active after adding rounds of cuts (0.016 seconds)
Clique was tried 100 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.001 seconds)
MixedIntegerRounding2 was tried 100 times and created 276 cuts of which 0 were active after adding rounds of cuts (0.014 seconds)
FlowCover was tried 100 times and created 20 cuts of which 0 were active after adding rounds of cuts (0.014 seconds)
TwoMirCuts was tried 100 times and created 236 cuts of which 0 were active after adding rounds of cuts (0.007 seconds)
ZeroHalf was tried 1 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
ImplicationCuts was tried 12 times and created 74 cuts of which 0 were active after adding rounds of cuts (0.001 seconds)

Result - Optimal solution found

Objective value:                5.00000000
Enumerated nodes:               6
Total iterations:               2531
Time (CPU seconds):             0.24
Time (Wallclock seconds):       0.24

Option for printingOptions changed from normal to all
Total time (CPU seconds):       0.24   (Wallclock seconds):       0.24

Welcome to the CBC MILP Solver
Version: 2.10.3
Build Date: Dec 15 2019

command line - /home/nduminy/.pyenv/versions/3.10.7/envs/pymcda-test/lib/python3.10/site-packages/pulp/solverdir/cbc/linux/64/cbc /tmp/6012949039464270b2189744844dd5fd-pulp.mps max timeMode elapsed branch printingOptions all solution /tmp/6012949039464270b2189744844dd5fd-pulp.sol (default strategy 1)
At line 2 NAME          MODEL
At line 3 ROWS
At line 427 COLUMNS
At line 1717 RHS
At line 2140 BOUNDS
At line 2290 ENDATA
Problem MODEL has 422 rows, 149 columns and 1135 elements
Coin0008I MODEL read with 0 errors
Option for timeMode changed from cpu to elapsed
Continuous objective value is 6 - 0.00 seconds
Cgl0002I 4 variables fixed
Cgl0003I 0 fixed, 0 tightened bounds, 234 strengthened rows, 12 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 50 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 24 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 6 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 0 tightened bounds, 1 strengthened rows, 0 substitutions
Cgl0004I processed model has 265 rows, 113 columns (50 integer (50 of which binary)) and 1021 elements
Cbc0045I 4 integer variables out of 50 objects (50 integer) have cost of -1 - high priority
Cbc0045I branch on satisfied Y create fake objective Y random cost Y
Cbc0038I Initial state - 9 integers unsatisfied sum - 2.54009
Cbc0038I Pass   1: suminf.    0.13950 (8) obj. -6 iterations 56
Cbc0038I Pass   2: suminf.    0.66817 (7) obj. -5.93298 iterations 41
Cbc0038I Pass   3: suminf.    0.54000 (5) obj. -5.98 iterations 13
Cbc0038I Pass   4: suminf.    0.57850 (5) obj. -5 iterations 21
Cbc0038I Pass   5: suminf.    0.52495 (4) obj. -5 iterations 8
Cbc0038I Pass   6: suminf.    0.57709 (5) obj. -5 iterations 23
Cbc0038I Pass   7: suminf.    0.52000 (4) obj. -5 iterations 14
Cbc0038I Pass   8: suminf.    2.67583 (14) obj. -5 iterations 73
Cbc0038I Pass   9: suminf.    1.13367 (6) obj. -5 iterations 20
Cbc0038I Pass  10: suminf.    0.02980 (2) obj. -5 iterations 19
Cbc0038I Pass  11: suminf.    0.01990 (2) obj. -5 iterations 10
Cbc0038I Pass  12: suminf.    2.23988 (11) obj. -5 iterations 40
Cbc0038I Pass  13: suminf.    0.52480 (5) obj. -5 iterations 45
Cbc0038I Pass  14: suminf.    0.02000 (2) obj. -5 iterations 13
Cbc0038I Pass  15: suminf.    0.01980 (2) obj. -5 iterations 5
Cbc0038I Pass  16: suminf.    1.21119 (10) obj. -5 iterations 38
Cbc0038I Pass  17: suminf.    0.69357 (7) obj. -5 iterations 13
Cbc0038I Pass  18: suminf.    0.17906 (2) obj. -5 iterations 21
Cbc0038I Pass  19: suminf.    0.27105 (2) obj. -5 iterations 6
Cbc0038I Pass  20: suminf.    4.25933 (19) obj. -4 iterations 78
Cbc0038I Pass  21: suminf.    2.08028 (15) obj. -4 iterations 17
Cbc0038I Pass  22: suminf.    1.30050 (13) obj. -4 iterations 5
Cbc0038I Pass  23: suminf.    0.52139 (5) obj. -4 iterations 45
Cbc0038I Pass  24: suminf.    0.27000 (3) obj. -4 iterations 22
Cbc0038I Pass  25: suminf.    0.01980 (1) obj. -4 iterations 11
Cbc0038I Pass  26: suminf.    0.02000 (1) obj. -4 iterations 1
Cbc0038I Pass  27: suminf.    1.63179 (7) obj. -4 iterations 28
Cbc0038I Pass  28: suminf.    0.90755 (6) obj. -4 iterations 8
Cbc0038I Pass  29: suminf.    0.20162 (3) obj. -4 iterations 16
Cbc0038I Pass  30: suminf.    0.02000 (1) obj. -4 iterations 13
Cbc0038I Pass  31: suminf.    0.01980 (1) obj. -4 iterations 3
Cbc0038I Pass  32: suminf.    0.51648 (3) obj. -5 iterations 25
Cbc0038I Pass  33: suminf.    0.51648 (3) obj. -5 iterations 3
Cbc0038I Pass  34: suminf.    0.18162 (2) obj. -5 iterations 16
Cbc0038I Pass  35: suminf.    0.09080 (4) obj. -4.99 iterations 16
Cbc0038I Pass  36: suminf.    0.02980 (2) obj. -4 iterations 17
Cbc0038I Pass  37: suminf.    0.02000 (1) obj. -4 iterations 5
Cbc0038I Pass  38: suminf.    0.01980 (1) obj. -4 iterations 3
Cbc0038I Pass  39: suminf.    3.00913 (12) obj. -4 iterations 59
Cbc0038I Pass  40: suminf.    1.48897 (7) obj. -4 iterations 12
Cbc0038I Pass  41: suminf.    0.14437 (2) obj. -4 iterations 29
Cbc0038I Pass  42: suminf.    0.25743 (1) obj. -4 iterations 9
Cbc0038I Pass  43: suminf.    0.25000 (1) obj. -4 iterations 1
Cbc0038I Pass  44: suminf.    0.43667 (4) obj. -4 iterations 30
Cbc0038I Pass  45: suminf.    0.12333 (4) obj. -4 iterations 4
Cbc0038I Pass  46: suminf.    0.00000 (0) obj. -4 iterations 11
Cbc0038I Solution found of -4
Cbc0038I Relaxing continuous gives -4
Cbc0038I Rounding solution of -5 is better than previous of -4

Cbc0038I Before mini branch and bound, 3 integers at bound fixed and 6 continuous
Cbc0038I Full problem 265 rows 113 columns, reduced to 250 rows 104 columns - 1 fixed gives 249, 103 - still too large
Cbc0038I Mini branch and bound did not improve solution (0.04 seconds)
Cbc0038I Round again with cutoff of -5.99991
Cbc0038I Reduced cost fixing fixed 4 variables on major pass 2
Cbc0038I Pass  47: suminf.    0.13950 (8) obj. -6 iterations 0
Cbc0038I Pass  48: suminf.    0.66750 (7) obj. -6 iterations 59
Cbc0038I Pass  49: suminf.    0.53980 (5) obj. -6 iterations 11
Cbc0038I Pass  50: suminf.    0.74221 (7) obj. -6 iterations 24
Cbc0038I Pass  51: suminf.    0.54495 (5) obj. -6 iterations 12
Cbc0038I Pass  52: suminf.    0.74988 (6) obj. -6 iterations 22
Cbc0038I Pass  53: suminf.    1.16678 (13) obj. -6 iterations 63
Cbc0038I Pass  54: suminf.    0.92229 (9) obj. -6 iterations 17
Cbc0038I Pass  55: suminf.    0.75060 (5) obj. -6 iterations 51
Cbc0038I Pass  56: suminf.    0.17657 (2) obj. -6 iterations 7
Cbc0038I Pass  57: suminf.    0.12000 (2) obj. -6 iterations 9
Cbc0038I Pass  58: suminf.    0.02990 (2) obj. -6 iterations 5
Cbc0038I Pass  59: suminf.    1.03190 (4) obj. -6 iterations 29
Cbc0038I Pass  60: suminf.    0.06000 (3) obj. -6 iterations 20
Cbc0038I Pass  61: suminf.    0.11990 (2) obj. -6 iterations 8
Cbc0038I Pass  62: suminf.    0.05000 (2) obj. -6 iterations 6
Cbc0038I Pass  63: suminf.    2.25388 (13) obj. -6 iterations 32
Cbc0038I Pass  64: suminf.    0.60166 (9) obj. -6 iterations 21
Cbc0038I Pass  65: suminf.    0.59319 (8) obj. -6 iterations 6
Cbc0038I Pass  66: suminf.    0.54318 (3) obj. -6 iterations 21
Cbc0038I Pass  67: suminf.    0.12280 (3) obj. -6 iterations 12
Cbc0038I Pass  68: suminf.    0.22868 (3) obj. -6 iterations 12
Cbc0038I Pass  69: suminf.    0.19990 (3) obj. -6 iterations 22
Cbc0038I Pass  70: suminf.    0.12000 (2) obj. -6 iterations 11
Cbc0038I Pass  71: suminf.    0.02990 (2) obj. -6 iterations 5
Cbc0038I Pass  72: suminf.    2.33034 (11) obj. -6 iterations 52
Cbc0038I Pass  73: suminf.    0.85947 (7) obj. -6 iterations 8
Cbc0038I Pass  74: suminf.    0.78907 (9) obj. -6 iterations 9
Cbc0038I Pass  75: suminf.    0.54000 (7) obj. -6 iterations 28
Cbc0038I Pass  76: suminf.    0.80487 (5) obj. -6 iterations 14
Cbc0038I Pass  77: suminf.    0.14000 (3) obj. -6 iterations 17
Cbc0038I Pass  78: suminf.    0.21323 (3) obj. -6 iterations 14
Cbc0038I Pass  79: suminf.    0.03000 (2) obj. -6 iterations 10
Cbc0038I Pass  80: suminf.    0.11990 (2) obj. -6 iterations 5
Cbc0038I Pass  81: suminf.    0.44349 (5) obj. -6 iterations 34
Cbc0038I Pass  82: suminf.    0.39254 (3) obj. -6 iterations 5
Cbc0038I Pass  83: suminf.    0.02000 (2) obj. -6 iterations 15
Cbc0038I Pass  84: suminf.    0.58387 (3) obj. -6 iterations 10
Cbc0038I Pass  85: suminf.    0.03000 (3) obj. -6 iterations 11
Cbc0038I Pass  86: suminf.    0.21603 (4) obj. -6 iterations 14
Cbc0038I Pass  87: suminf.    0.37000 (3) obj. -6 iterations 15
Cbc0038I Pass  88: suminf.    0.12270 (3) obj. -6 iterations 11
Cbc0038I Pass  89: suminf.    1.94595 (12) obj. -6 iterations 46
Cbc0038I Pass  90: suminf.    0.55192 (6) obj. -6 iterations 13
Cbc0038I Pass  91: suminf.    0.65812 (7) obj. -6 iterations 28
Cbc0038I Pass  92: suminf.    0.14380 (5) obj. -6 iterations 9
Cbc0038I Pass  93: suminf.    0.11990 (2) obj. -6 iterations 14
Cbc0038I Pass  94: suminf.    0.03000 (2) obj. -6 iterations 4
Cbc0038I Pass  95: suminf.    2.16973 (10) obj. -6 iterations 34
Cbc0038I Pass  96: suminf.    1.45646 (9) obj. -6 iterations 7
Cbc0038I Pass  97: suminf.    1.33310 (9) obj. -6 iterations 41
Cbc0038I Pass  98: suminf.    0.15990 (3) obj. -6 iterations 29
Cbc0038I Pass  99: suminf.    0.11990 (2) obj. -6 iterations 4
Cbc0038I Pass 100: suminf.    0.03000 (2) obj. -6 iterations 4
Cbc0038I Pass 101: suminf.    1.11914 (7) obj. -6 iterations 26
Cbc0038I Pass 102: suminf.    0.62865 (4) obj. -6 iterations 7
Cbc0038I Pass 103: suminf.    0.11990 (2) obj. -6 iterations 9
Cbc0038I Pass 104: suminf.    0.05000 (2) obj. -6 iterations 14
Cbc0038I Pass 105: suminf.    1.03752 (16) obj. -6 iterations 49
Cbc0038I Pass 106: suminf.    0.82513 (9) obj. -6 iterations 14
Cbc0038I Pass 107: suminf.    0.17990 (2) obj. -6 iterations 30
Cbc0038I Pass 108: suminf.    0.12000 (2) obj. -6 iterations 7
Cbc0038I Pass 109: suminf.    0.02990 (2) obj. -6 iterations 8
Cbc0038I Pass 110: suminf.    2.12656 (11) obj. -6 iterations 30
Cbc0038I Pass 111: suminf.    0.37280 (7) obj. -6 iterations 19
Cbc0038I Pass 112: suminf.    0.57140 (6) obj. -6 iterations 33
Cbc0038I Pass 113: suminf.    0.11990 (2) obj. -6 iterations 18
Cbc0038I Pass 114: suminf.    0.03000 (2) obj. -6 iterations 7
Cbc0038I Pass 115: suminf.    3.50534 (14) obj. -6 iterations 54
Cbc0038I Pass 116: suminf.    1.34126 (11) obj. -6 iterations 16
Cbc0038I Pass 117: suminf.    0.84102 (11) obj. -6 iterations 15
Cbc0038I Pass 118: suminf.    0.24080 (3) obj. -6 iterations 23
Cbc0038I Pass 119: suminf.    0.01000 (1) obj. -6 iterations 10
Cbc0038I Pass 120: suminf.    0.01980 (1) obj. -6 iterations 2
Cbc0038I Pass 121: suminf.    0.80815 (8) obj. -6 iterations 32
Cbc0038I Pass 122: suminf.    0.80815 (8) obj. -6 iterations 0
Cbc0038I Pass 123: suminf.    0.62541 (5) obj. -6 iterations 24
Cbc0038I Pass 124: suminf.    0.36822 (3) obj. -6 iterations 27
Cbc0038I Pass 125: suminf.    0.28000 (2) obj. -6 iterations 14
Cbc0038I Pass 126: suminf.    0.19822 (2) obj. -6 iterations 13
Cbc0038I Pass 127: suminf.    4.43043 (19) obj. -6 iterations 72
Cbc0038I Pass 128: suminf.    2.33130 (14) obj. -6 iterations 14
Cbc0038I Pass 129: suminf.    1.93209 (14) obj. -6 iterations 5
Cbc0038I Pass 130: suminf.    1.30290 (11) obj. -6 iterations 5
Cbc0038I Pass 131: suminf.    0.40816 (5) obj. -6 iterations 48
Cbc0038I Pass 132: suminf.    0.20000 (6) obj. -6 iterations 8
Cbc0038I Pass 133: suminf.    0.29579 (3) obj. -6 iterations 19
Cbc0038I Pass 134: suminf.    0.03990 (3) obj. -6 iterations 6
Cbc0038I Pass 135: suminf.    0.38316 (3) obj. -6 iterations 11
Cbc0038I Pass 136: suminf.    0.13000 (3) obj. -6 iterations 4
Cbc0038I Pass 137: suminf.    0.30147 (4) obj. -6 iterations 31
Cbc0038I Pass 138: suminf.    0.02495 (4) obj. -6 iterations 14
Cbc0038I Pass 139: suminf.    0.34667 (3) obj. -6 iterations 20
Cbc0038I Pass 140: suminf.    0.21000 (1) obj. -6 iterations 6
Cbc0038I Pass 141: suminf.    0.00990 (1) obj. -6 iterations 4
Cbc0038I Pass 142: suminf.    0.01000 (1) obj. -6 iterations 2
Cbc0038I Pass 143: suminf.    1.28147 (10) obj. -6 iterations 38
Cbc0038I Pass 144: suminf.    1.28147 (10) obj. -6 iterations 2
Cbc0038I Pass 145: suminf.    0.20137 (4) obj. -6 iterations 29
Cbc0038I Pass 146: suminf.    1.57224 (8) obj. -6 iterations 35
Cbc0038I No solution found this major pass
Cbc0038I Before mini branch and bound, 6 integers at bound fixed and 4 continuous
Cbc0038I Full problem 265 rows 113 columns, reduced to 255 rows 103 columns - 3 fixed gives 246, 100 - still too large
Cbc0038I Mini branch and bound did not improve solution (0.09 seconds)
Cbc0038I After 0.09 seconds - Feasibility pump exiting with objective of -5 - took 0.08 seconds
Cbc0012I Integer solution of -5 found by feasibility pump after 0 iterations and 0 nodes (0.09 seconds)
Cbc0038I Full problem 265 rows 113 columns, reduced to 116 rows 46 columns
Cbc0031I 41 added rows had average density of 17.609756
Cbc0013I At root node, 41 cuts changed objective from -6 to -6 in 13 passes
Cbc0014I Cut generator 0 (Probing) - 229 row cuts average 6.3 elements, 0 column cuts (0 active)  in 0.005 seconds - new frequency is -100
Cbc0014I Cut generator 1 (Gomory) - 70 row cuts average 58.8 elements, 0 column cuts (0 active)  in 0.002 seconds - new frequency is -100
Cbc0014I Cut generator 2 (Knapsack) - 14 row cuts average 5.7 elements, 0 column cuts (0 active)  in 0.003 seconds - new frequency is -100
Cbc0014I Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 4 (MixedIntegerRounding2) - 71 row cuts average 11.4 elements, 0 column cuts (0 active)  in 0.003 seconds - new frequency is -100
Cbc0014I Cut generator 5 (FlowCover) - 1 row cuts average 2.0 elements, 0 column cuts (0 active)  in 0.002 seconds - new frequency is -100
Cbc0014I Cut generator 6 (TwoMirCuts) - 76 row cuts average 38.4 elements, 0 column cuts (0 active)  in 0.002 seconds - new frequency is -100
Cbc0010I After 0 nodes, 1 on tree, -5 best solution, best possible -6 (0.13 seconds)
Cbc0038I Full problem 265 rows 113 columns, reduced to 100 rows 41 columns
Cbc0038I Full problem 265 rows 113 columns, reduced to 91 rows 37 columns
Cbc0038I Full problem 265 rows 113 columns, reduced to 95 rows 40 columns
Cbc0012I Integer solution of -6 found by DiveCoefficient after 9892 iterations and 290 nodes (0.57 seconds)
Cbc0001I Search completed - best objective -6, took 9892 iterations and 290 nodes (0.57 seconds)
Cbc0032I Strong branching done 2074 times (23738 iterations), fathomed 123 nodes and fixed 46 variables
Cbc0035I Maximum depth 13, 4 variables fixed on reduced cost
Cuts at root node changed objective from -6 to -6
Probing was tried 13 times and created 229 cuts of which 0 were active after adding rounds of cuts (0.005 seconds)
Gomory was tried 13 times and created 70 cuts of which 0 were active after adding rounds of cuts (0.002 seconds)
Knapsack was tried 13 times and created 14 cuts of which 0 were active after adding rounds of cuts (0.003 seconds)
Clique was tried 13 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 13 times and created 71 cuts of which 0 were active after adding rounds of cuts (0.003 seconds)
FlowCover was tried 13 times and created 1 cuts of which 0 were active after adding rounds of cuts (0.002 seconds)
TwoMirCuts was tried 13 times and created 76 cuts of which 0 were active after adding rounds of cuts (0.002 seconds)
ZeroHalf was tried 1 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
ImplicationCuts was tried 33 times and created 284 cuts of which 0 were active after adding rounds of cuts (0.001 seconds)

Result - Optimal solution found

Objective value:                6.00000000
Enumerated nodes:               290
Total iterations:               9892
Time (CPU seconds):             0.57
Time (Wallclock seconds):       0.57

Option for printingOptions changed from normal to all
Total time (CPU seconds):       0.57   (Wallclock seconds):       0.57

[84]:
../../_images/notebooks_examples_outranking_algorithms_130_1.svg
[ ]: