Skip to content

Commit 18bc95d

Browse files
authored
Merge pull request #67 from IBMDecisionOptimization/prepare_2.23.222
updated with 2.23
2 parents f4662be + 994e7dd commit 18bc95d

File tree

10 files changed

+598
-10
lines changed

10 files changed

+598
-10
lines changed

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ This library is numpy friendly.
2424

2525
## Get the documentation and examples
2626

27-
* [Documentation](http://ibmdecisionoptimization.github.io/docplex-doc/)
27+
* [Latest documentation](http://ibmdecisionoptimization.github.io/docplex-doc/)
28+
* Documentation archives:
29+
* [2.23.217](http://ibmdecisionoptimization.github.io/docplex-doc/2.23.217)
30+
* [2.22.213](http://ibmdecisionoptimization.github.io/docplex-doc/2.22.213)
31+
* [2.21.207](http://ibmdecisionoptimization.github.io/docplex-doc/2.21.207)
32+
* [2.20.204](http://ibmdecisionoptimization.github.io/docplex-doc/2.20.204)
33+
* [2.19.202](http://ibmdecisionoptimization.github.io/docplex-doc/2.19.202)
34+
* [2.18.200](http://ibmdecisionoptimization.github.io/docplex-doc/2.18.200)
35+
* [2.16.195](http://ibmdecisionoptimization.github.io/docplex-doc/2.16.195)
2836
* [Examples](https://github.com/IBMDecisionOptimization/docplex-examples)
2937

3038
## Get your IBM® ILOG CPLEX Optimization Studio edition
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
10 10
2+
0 2500 3300 1 7400 8200 2 900 900 3 3200 4000 4 4900 4900 5 1100 1100 6 5900 6500 7 5600 5600 8 3900 4900 9 2000 2200
3+
0 3900 4700 2 8900 9100 4 6700 8300 9 1100 1100 3 6300 7500 1 2500 3100 6 4600 4600 5 4300 4900 7 7100 7300 8 2700 3300
4+
1 8600 9600 0 7700 9300 3 3400 4400 2 6400 8400 8 8900 9100 5 1000 1000 7 1100 1300 6 8700 9100 9 4100 4900 4 3100 3500
5+
1 7900 8300 2 9400 9600 0 6200 8000 4 9200 10600 6 900 900 8 4600 5800 7 7400 9600 3 9000 10600 9 2100 2300 5 4100 4500
6+
2 1300 1500 0 600 600 1 2200 2200 5 5300 6900 3 2500 2700 4 6400 7400 8 2000 2200 7 4600 5200 9 7200 7200 6 4600 6000
7+
2 7500 9300 1 200 200 5 5200 5200 3 8900 10100 8 4300 5300 9 7000 7400 0 4400 5000 6 6200 6800 4 600 600 7 2300 2700
8+
1 4300 4900 0 3400 4000 3 6000 6200 2 1300 1300 6 2800 3600 5 2000 2200 9 2900 3500 8 8300 9500 7 2900 3100 4 5400 5600
9+
2 2900 3300 0 8600 8600 1 4600 4600 5 6500 8300 4 2900 3500 6 7900 9700 8 1700 2100 9 4500 5100 7 3500 3700 3 6900 8900
10+
0 7200 8000 1 6300 7500 3 6700 8500 5 5100 5100 2 7700 9300 9 1000 1200 6 3600 4400 7 8300 9500 4 2600 2600 8 7300 7500
11+
1 8100 8900 0 1300 1300 2 5800 6400 6 700 700 8 5900 6900 9 7000 8200 5 4600 4800 3 5000 5400 4 8200 9800 7 4100 4900

examples/cp/basic/kmeans.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# --------------------------------------------------------------------------
2+
# Source file provided under Apache License, Version 2.0, January 2004,
3+
# http://www.apache.org/licenses/
4+
# (c) Copyright IBM Corp. 2021, 2022
5+
# --------------------------------------------------------------------------
6+
7+
"""
8+
K-means is a way of clustering points in a multi-dimensional space
9+
where the set of points to be clustered are partitioned into k subsets.
10+
The idea is to minimize the inter-point distances inside a cluster in
11+
order to produce clusters which group together close points.
12+
13+
See https://en.wikipedia.org/wiki/K-means_clustering
14+
"""
15+
16+
17+
import numpy as np
18+
from docplex.cp.model import CpoModel
19+
import docplex.cp.solver.solver as solver
20+
from docplex.cp.utils import compare_natural
21+
22+
def make_model(coords, k, trust_numerics=True):
23+
"""
24+
Build a K-means model from a set of coordinate vectors (points),
25+
and a given number of clusters k.
26+
27+
We assign each point to a cluster and minimize the objective which
28+
is the sum of the squares of the distances of each point to
29+
the centre of gravity of the cluster to which it belongs.
30+
31+
Here, there are two ways of building the objective function. One
32+
uses the sum of squares of the coordinates of points in a cluster
33+
minus the size of the cluster times the center value. This is akin
34+
to the calculation of variance vi E[X^2] - E[X]^2. This is the most
35+
efficient but can be numerically unstable due to massive cancellation.
36+
37+
The more numerically stable (but less efficient) way to calculate the
38+
objective is the analog of the variance calculation (sum_i(X_i - mu_i)^2)/n
39+
"""
40+
# Sizes and ranges
41+
n, d = coords.shape
42+
N, D, K = range(n), range(d), range(k)
43+
44+
# Model, and decision variables. x[c] = cluster to which node c belongs
45+
mdl = CpoModel()
46+
x = [mdl.integer_var(0, k-1, "C_{}".format(i)) for i in N]
47+
48+
# Size (number of nodes) in each cluster. If this is zero, we make
49+
# it 1 to avoid division by zero later (if a particular cluster is
50+
# not used).
51+
csize = [mdl.max(1, mdl.count(x, c)) for c in K]
52+
53+
# Calculate total distance squared
54+
total_dist2 = 0
55+
for c in K: # For each cluster
56+
# Boolean vector saying which points are in this cluster
57+
included = [x[i] == c for i in N]
58+
for dim in D: # For each dimension
59+
# Points for each point in the given dimension (x, y, z, ...)
60+
point = coords[:, dim]
61+
62+
# Calculate the cluster centre for this dimension
63+
centre = mdl.scal_prod(included, point) / csize[c]
64+
65+
# Calculate the total distance^2 for this cluster & dimension
66+
if trust_numerics:
67+
sum_of_x2 = mdl.scal_prod(included, (p**2 for p in point))
68+
dist2 = sum_of_x2 - centre**2 * csize[c]
69+
else:
70+
all_dist2 = ((centre - p)**2 for p in point)
71+
dist2 = mdl.scal_prod(included, all_dist2)
72+
73+
# Keep the total distance squared in a sum
74+
total_dist2 += dist2
75+
76+
# Minimize the total distance squared
77+
mdl.minimize(total_dist2)
78+
return mdl
79+
80+
81+
if __name__ == "__main__":
82+
import sys
83+
# Default values
84+
n, d, k, sd = 500, 2, 5, 1234
85+
86+
# Accept number of points, number of dimensions, number of clusters, seed
87+
if len(sys.argv) > 1:
88+
n = int(sys.argv[1])
89+
if len(sys.argv) > 2:
90+
d = int(sys.argv[2])
91+
if len(sys.argv) > 3:
92+
k = int(sys.argv[3])
93+
if len(sys.argv) > 4:
94+
sd = int(sys.argv[4])
95+
96+
# Message
97+
print("Generating with N = {}, D = {}, K = {}".format(n, d, k))
98+
99+
# Seed and generate coordinates on the unit hypercube
100+
np.random.seed(sd)
101+
coords = np.random.uniform(0, 1, size=(n, d))
102+
103+
# Build model
104+
mdl = make_model(coords, k)
105+
106+
# Solve using constraint programming
107+
mdl.solve(SearchType="Restart", TimeLimit=10, LogPeriod=50000)
108+
109+
if compare_natural(solver.get_solver_version(), '22.1') >= 0:
110+
# Solve using neighborhood search
111+
mdl.solve(SearchType="Neighborhood", TimeLimit=10, LogPeriod=50000)

examples/cp/basic/plant_location_with_kpis.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"""
3838

3939
from docplex.cp.model import CpoModel
40-
from docplex.cp.config import context
40+
import docplex.cp.solver.solver as solver
4141
from docplex.cp.utils import compare_natural
4242
from collections import deque
4343
import os
@@ -99,7 +99,8 @@
9999
mdl.add(mdl.minimize(obj))
100100

101101
# Add KPIs
102-
if context.model.version is None or compare_natural(context.model.version, '12.9') >= 0:
102+
sol_version = solver.get_solver_version()
103+
if compare_natural(sol_version, '12.9') >= 0:
103104
mdl.add_kpi(mdl.sum(demand) / mdl.scal_prod(open, capacity), "Occupancy")
104105
mdl.add_kpi(mdl.min([load[l] / capacity[l] + (1 - open[l]) for l in range(nbLocation)]), "Min occupancy")
105106

@@ -113,7 +114,7 @@
113114
msol = mdl.solve(TimeLimit=10, trace_log=False) # Set trace_log=True to have a real-time view of the KPIs
114115
if msol:
115116
print(" Objective value: {}".format(msol.get_objective_values()[0]))
116-
if context.model.version is None or compare_natural(context.model.version, '12.9') >= 0:
117+
if compare_natural(sol_version, '12.9') >= 0:
117118
print(" KPIs: {}".format(msol.get_kpis()))
118119
else:
119120
print(" No solution")

0 commit comments

Comments
 (0)