Show the code
using Pkg
Pkg.activate(@__DIR__)
Pkg.instantiate()
using JuMP, DataFrames, CSV, Plots, HiGHS
Activating project at `~/proyectos_personales/blog_quarto/2025/07`
José Luis Cañadas Reche
July 20, 2025
Este post viene a ampliar el de la IO al servicio del mal. y está en Work in Progress.
Activating project at `~/proyectos_personales/blog_quarto/2025/07`
Row | cod_postal | cod_prov | area_m2 | centroide_longitud | centroide_latitud | provincia |
---|---|---|---|---|---|---|
Int64 | Int64 | Float64 | Float64 | Float64 | String31 | |
1 | 35560 | 35 | 1.87875e8 | -13.703 | 29.0501 | PALMAS, LAS |
2 | 27330 | 27 | 6.65941e6 | -7.3956 | 42.5614 | LUGO |
3 | 46680 | 46 | 6.91908e7 | -0.429241 | 39.2137 | VALENCIA/VALENCIA |
4 | 49706 | 49 | 9.02291e7 | -5.726 | 41.3027 | ZAMORA |
5 | 21120 | 21 | 2.00686e7 | -6.99673 | 37.2879 | HUELVA |
6 | 16623 | 16 | 1.3286e8 | -2.35389 | 39.6706 | CUENCA |
7 | 10650 | 10 | 8.92692e7 | -6.20114 | 40.1693 | CACERES |
8 | 37111 | 37 | 1.01925e8 | -5.89406 | 41.1513 | SALAMANCA |
9 | 44124 | 44 | 4.63729e7 | -1.55171 | 40.3196 | TERUEL |
10 | 33150 | 33 | 1.57172e6 | -6.14814 | 43.5619 | ASTURIAS |
11 | 41910 | 41 | 2.33707e6 | -6.0401 | 37.3883 | SEVILLA |
12 | 28597 | 28 | 1.03083e8 | -3.15911 | 40.111 | MADRID |
13 | 3838 | 3 | 3.26148e7 | -0.563752 | 38.7809 | ALICANTE/ALACANT |
⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ |
10797 | 45635 | 45 | 3.22399e7 | -4.84787 | 40.0932 | TOLEDO |
10798 | 36859 | 36 | 8.31546e6 | -8.54405 | 42.4389 | PONTEVEDRA |
10799 | 37554 | 37 | 3.34345e7 | -6.81653 | 40.4588 | SALAMANCA |
10800 | 7190 | 7 | 7.04852e7 | 2.58113 | 39.6665 | BALEARS, ILLES |
10801 | 8280 | 8 | 1.65922e7 | 1.50624 | 41.7216 | BARCELONA |
10802 | 27146 | 27 | 4.13968e7 | -7.43692 | 43.0169 | LUGO |
10803 | 45006 | 45 | 3.70004e7 | -3.99207 | 39.8375 | TOLEDO |
10804 | 47493 | 47 | 1.07702e8 | -4.86432 | 41.2334 | VALLADOLID |
10805 | 50547 | 50 | 1.75265e8 | -1.51964 | 41.697 | ZARAGOZA |
10806 | 27460 | 27 | 1.43119e7 | -7.58225 | 42.4526 | LUGO |
10807 | 28921 | 28 | 9.61587e5 | -3.8276 | 40.3477 | MADRID |
10808 | 14140 | 14 | 3.0837e7 | -4.8546 | 37.6964 | CORDOBA |
Seleccionamos solo Andalucía. Tanto para las sedes como para las códigos postales
Row | cod_postal | tipo | cod_prov | area_m2 | centroide_longitud | centroide_latitud | provincia |
---|---|---|---|---|---|---|---|
Int64 | String7 | Int64 | Float64 | Float64 | Float64 | String31 | |
1 | 4727 | jefe | 4 | 9.58884e6 | -2.62205 | 36.8347 | ALMERIA |
2 | 11600 | jefe | 11 | 1.08706e8 | -5.46371 | 36.6586 | CADIZ |
3 | 14659 | jefe | 14 | 2.76092e7 | -4.42429 | 37.9386 | CORDOBA |
4 | 18328 | jefe | 18 | 5.85745e7 | -3.87328 | 37.1906 | GRANADA |
5 | 21387 | jefe | 21 | 2.19028e7 | -6.69674 | 38.0752 | HUELVA |
6 | 23369 | jefe | 23 | 1.2085e8 | -2.80429 | 38.3832 | JAEN |
7 | 29531 | jefe | 29 | 1.24176e8 | -4.74224 | 37.1056 | MALAGA |
8 | 41760 | jefe | 41 | 1.44046e8 | -5.61951 | 37.0264 | SEVILLA |
9 | 41599 | jefe | 41 | 8.47675e7 | -4.72387 | 37.2476 | SEVILLA |
10 | 14729 | jefe | 14 | 1.71617e8 | -4.99471 | 37.855 | CORDOBA |
11 | 18006 | jefe | 18 | 3.24591e6 | -3.60903 | 37.1606 | GRANADA |
12 | 14547 | jefe | 14 | 1.88571e8 | -4.83313 | 37.5774 | CORDOBA |
13 | 14430 | jefe | 14 | 5.04828e8 | -4.57405 | 38.0962 | CORDOBA |
⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ |
65 | 11611 | indio | 11 | 9.26568e7 | -5.36712 | 36.6863 | CADIZ |
66 | 14913 | indio | 14 | 4.36996e7 | -4.48437 | 37.2767 | CORDOBA |
67 | 21387 | indio | 21 | 2.19028e7 | -6.69674 | 38.0752 | HUELVA |
68 | 14913 | indio | 14 | 4.36996e7 | -4.48437 | 37.2767 | CORDOBA |
69 | 4727 | indio | 4 | 9.58884e6 | -2.62205 | 36.8347 | ALMERIA |
70 | 11406 | indio | 11 | 2.57144e7 | -6.10322 | 36.6714 | CADIZ |
71 | 14659 | indio | 14 | 2.76092e7 | -4.42429 | 37.9386 | CORDOBA |
72 | 14191 | indio | 14 | 2.36389e7 | -4.89704 | 37.7 | CORDOBA |
73 | 4727 | indio | 4 | 9.58884e6 | -2.62205 | 36.8347 | ALMERIA |
74 | 29580 | indio | 29 | 8.54712e7 | -4.62152 | 36.7579 | MALAGA |
75 | 21594 | indio | 21 | 1.55329e8 | -7.42947 | 37.5182 | HUELVA |
76 | 29716 | indio | 29 | 4.602e7 | -4.08153 | 36.8767 | MALAGA |
Ordenamos el dataset de sedes por si son jefes o indios
Row | cod_postal | tipo | cod_prov | area_m2 | centroide_longitud | centroide_latitud | provincia |
---|---|---|---|---|---|---|---|
Int64 | String7 | Int64 | Float64 | Float64 | Float64 | String31 | |
1 | 4727 | jefe | 4 | 9.58884e6 | -2.62205 | 36.8347 | ALMERIA |
2 | 11600 | jefe | 11 | 1.08706e8 | -5.46371 | 36.6586 | CADIZ |
3 | 14659 | jefe | 14 | 2.76092e7 | -4.42429 | 37.9386 | CORDOBA |
4 | 18328 | jefe | 18 | 5.85745e7 | -3.87328 | 37.1906 | GRANADA |
5 | 21387 | jefe | 21 | 2.19028e7 | -6.69674 | 38.0752 | HUELVA |
6 | 23369 | jefe | 23 | 1.2085e8 | -2.80429 | 38.3832 | JAEN |
7 | 29531 | jefe | 29 | 1.24176e8 | -4.74224 | 37.1056 | MALAGA |
8 | 41760 | jefe | 41 | 1.44046e8 | -5.61951 | 37.0264 | SEVILLA |
9 | 41599 | jefe | 41 | 8.47675e7 | -4.72387 | 37.2476 | SEVILLA |
10 | 14729 | jefe | 14 | 1.71617e8 | -4.99471 | 37.855 | CORDOBA |
11 | 18006 | jefe | 18 | 3.24591e6 | -3.60903 | 37.1606 | GRANADA |
12 | 14547 | jefe | 14 | 1.88571e8 | -4.83313 | 37.5774 | CORDOBA |
13 | 14430 | jefe | 14 | 5.04828e8 | -4.57405 | 38.0962 | CORDOBA |
⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ |
65 | 11611 | indio | 11 | 9.26568e7 | -5.36712 | 36.6863 | CADIZ |
66 | 14913 | indio | 14 | 4.36996e7 | -4.48437 | 37.2767 | CORDOBA |
67 | 21387 | indio | 21 | 2.19028e7 | -6.69674 | 38.0752 | HUELVA |
68 | 14913 | indio | 14 | 4.36996e7 | -4.48437 | 37.2767 | CORDOBA |
69 | 4727 | indio | 4 | 9.58884e6 | -2.62205 | 36.8347 | ALMERIA |
70 | 11406 | indio | 11 | 2.57144e7 | -6.10322 | 36.6714 | CADIZ |
71 | 14659 | indio | 14 | 2.76092e7 | -4.42429 | 37.9386 | CORDOBA |
72 | 14191 | indio | 14 | 2.36389e7 | -4.89704 | 37.7 | CORDOBA |
73 | 4727 | indio | 4 | 9.58884e6 | -2.62205 | 36.8347 | ALMERIA |
74 | 29580 | indio | 29 | 8.54712e7 | -4.62152 | 36.7579 | MALAGA |
75 | 21594 | indio | 21 | 1.55329e8 | -7.42947 | 37.5182 | HUELVA |
76 | 29716 | indio | 29 | 4.602e7 | -4.08153 | 36.8767 | MALAGA |
Creamos funcion haversine que nos va a dar la distancia entre los puntos dada longitud y latitud. Hay que pasarle las longitudes y latitude y el radio estimado de la tierra.
"""
haversine(lat1, long1, lat2, long2, r = 6372.8)
Compute the haversine distance between two points on a sphere of radius `r`,
where the points are given by the latitude/longitude pairs `lat1/long1` and
`lat2/long2` (in degrees).
"""
function haversine(lat1, long1, lat2, long2, r = 6372.8)
lat1, long1 = deg2rad(lat1), deg2rad(long1)
lat2, long2 = deg2rad(lat2), deg2rad(long2)
hav(a, b) = sin((b - a) / 2)^2
inner_term = hav(lat1, lat2) + cos(lat1) * cos(lat2) * hav(long1, long2)
d = 2 * r * asin(sqrt(inner_term))
# Round distance to nearest kilometer.
return round( d, digits = 2)
end
Main.Notebook.haversine
y ahora calculamos las distancias entre todos los códigos postales y todas las sedes de los trabajadores. En Julia esto es muy rápido
# number of clients
n = size(cod_postales,1)
# number of comerciales (facilities)
m = size(sedes, 1)
# esto es como en python, una list comprehension
c = [haversine(
cod_postales.centroide_latitud[i], cod_postales.centroide_longitud[i],
sedes.centroide_latitud[j], sedes.centroide_longitud[j])
for i in 1:n, j in 1:m]
1199×76 Matrix{Float64}:
391.51 153.15 237.92 276.78 91.46 … 391.51 219.0 46.02 262.68
309.35 95.96 154.88 192.99 95.77 309.35 144.1 123.52 182.75
237.91 17.41 165.47 140.3 205.33 237.91 60.56 215.89 110.43
160.03 93.98 134.67 70.39 251.29 160.03 18.83 281.53 33.89
133.54 260.16 121.23 114.95 320.21 133.54 195.38 389.21 153.88
283.0 38.8 169.44 174.7 154.78 … 283.0 105.93 160.81 153.04
109.45 162.65 100.43 9.65 275.83 109.45 90.71 325.81 45.8
188.54 89.03 88.14 73.36 202.19 188.54 47.17 244.21 64.36
64.33 307.66 222.48 159.52 418.35 64.33 231.99 474.69 182.17
150.59 295.03 150.67 149.44 347.02 150.59 230.27 419.08 188.03
⋮ ⋱ ⋮
201.53 102.74 67.24 83.61 184.43 … 201.53 73.17 234.3 85.23
9.86 263.86 208.24 126.87 393.96 9.86 188.12 442.11 139.72
125.69 194.52 77.57 52.75 273.43 125.69 130.18 334.64 92.18
311.14 57.82 203.18 206.25 161.74 311.14 132.87 148.4 181.79
165.85 300.7 150.32 158.46 343.75 165.85 238.11 417.88 197.55
367.22 164.67 189.14 249.28 27.68 … 367.22 211.0 83.48 245.41
0.0 254.01 201.1 117.96 385.28 0.0 178.29 432.72 129.97
192.17 92.83 81.27 75.61 196.58 192.17 55.23 241.0 70.37
219.63 127.43 46.43 103.32 167.11 219.63 106.41 227.74 113.98
Ahora para hacer truco de que a los jefes les toque códigos postales más cercanos a su sede lo que hacemos es aumentar la distancia artificialmente.
Contamos cuantos jefes y cuantos indios hay.
Y ahora definimos el problema de optimización y sus restricciones
Definimos el modelo dónde x va a ser una matriz de variables binarias qeu va a indicar si un código postal (de 1 a n) se asigna a un comercial (jefe o indio) va de 1 a m. Y la variable y va a indicar si ese código postal (o tienda) está asignado o no. Si no está asignado entonces se podrá asignar a un comercial.
Ahora vamos a poner restricione está asignado o no. Si no está asignado entonces se podrá asignar a un comercial.
Ahora vamos a poner restriciones
Lo primero es definir una serie de restricciones de forma que a cada código postal sólo se le puede asignar un comercial. Eso se define haciendo que en la matriz X , que tiene n filas (sedes) y j columnas (comercials) , al sumar por fila el valor sea igual a 1. Es decir, a cada código postal sólo puede ir un comercial. (Se podría cambiar a que fueran 2 por ejemplo)
La siguiente restricción es poner que un comercial sólo puede ser asignado a un código postal (sede, tienda) que esté abierta.
Esto se hace haciendo que la matriz x[i,j] sea menor o igual que y[j]. puesto que y[j] vale 1 si la “tienda” está abierta, y por tanto si está cerrada vale 0 y x[i,j] por narices tiene que ser 0 , es decir, si la “tienda” ha sido asignada ya no se puede
Estas dos restricciones implican. - Cada código postal sólo puede ser visitado por un único comercial - Un comercial sólo puede ser asignado a una sede si esta está abierta
Si tengo 3 cod postales y 2 comerciales
sum(x[1,1], x[1,2]) == 1 # cod postal 1 → un solo comercial
sum(x[2,1], x[2,2]) == 1 # cod postal 2 → un solo comercial
sum(x[3,1], x[3,2]) == 1 # cod postal 3 → un solo comercial
x[i,j] <= y[j] # Solo puedes usar comercial j si está abierto
De esta forma, un comercial puede ir a varios códigos postales pero un código postal solo puede ser visitado por un comercial.
Ahora vamos con las restriciones diferenciadas según el tipo de comercial.
La restricción para los indios es que al menos tienen que visitar 3 códigos postales cada uno y como máximo 100. Mientras que para los jefes se impone que al menos tienen que visitar un código postal (si no, sería muy cantoso) y cómo máximo 10.
Si hacemos print(ufl) veremos las restricciones planteadas, pero son muchas.
Y con esto ya podemos plantear el objetivo. que va a ser
En Jump también podemos escribir la formulación en LaTex
$$ \begin{aligned}
\min\quad & y_{1} + y_{2} + y_{3} + y_{4} + y_{5} + y_{6} + y_{7} + y_{8} + y_{9} + y_{10} + y_{11} + y_{12} + y_{13} + y_{14} + y_{15} + y_{16} + y_{17} + y_{18} + y_{19} + y_{20} + y_{21} + y_{22} + y_{23} + y_{24} + y_{25} + y_{26} + y_{27} + y_{28} + y_{29} + y_{30} + [[\ldots\text{91064 terms omitted}\ldots]] + 186.957 x_{1170,76} + 253.81799999999998 x_{1171,76} + 150.07500000000002 x_{1172,76} + 53.352000000000004 x_{1173,76} + 96.066 x_{1174,76} + 162.18 x_{1175,76} + 161.39700000000002 x_{1176,76} + 80.82 x_{1177,76} + 87.507 x_{1178,76} + 78.68700000000001 x_{1179,76} + 209.214 x_{1180,76} + 146.025 x_{1181,76} + 165.366 x_{1182,76} + 156.89700000000002 x_{1183,76} + 86.36399999999999 x_{1184,76} + 96.696 x_{1185,76} + 34.74 x_{1186,76} + 122.463 x_{1187,76} + 93.222 x_{1188,76} + 154.746 x_{1189,76} + 165.123 x_{1190,76} + 76.70700000000001 x_{1191,76} + 125.748 x_{1192,76} + 82.962 x_{1193,76} + 163.611 x_{1194,76} + 177.79500000000002 x_{1195,76} + 220.869 x_{1196,76} + 116.973 x_{1197,76} + 63.333000000000006 x_{1198,76} + 102.58200000000001 x_{1199,76}\\
\text{Subject to} \quad & x_{1,1} + x_{1,2} + x_{1,3} + x_{1,4} + x_{1,5} + x_{1,6} + x_{1,7} + x_{1,8} + x_{1,9} + x_{1,10} + x_{1,11} + x_{1,12} + x_{1,13} + x_{1,14} + x_{1,15} + x_{1,16} + x_{1,17} + x_{1,18} + x_{1,19} + x_{1,20} + x_{1,21} + x_{1,22} + x_{1,23} + x_{1,24} + x_{1,25} + x_{1,26} + x_{1,27} + x_{1,28} + x_{1,29} + x_{1,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{1,47} + x_{1,48} + x_{1,49} + x_{1,50} + x_{1,51} + x_{1,52} + x_{1,53} + x_{1,54} + x_{1,55} + x_{1,56} + x_{1,57} + x_{1,58} + x_{1,59} + x_{1,60} + x_{1,61} + x_{1,62} + x_{1,63} + x_{1,64} + x_{1,65} + x_{1,66} + x_{1,67} + x_{1,68} + x_{1,69} + x_{1,70} + x_{1,71} + x_{1,72} + x_{1,73} + x_{1,74} + x_{1,75} + x_{1,76} = 1\\
& x_{2,1} + x_{2,2} + x_{2,3} + x_{2,4} + x_{2,5} + x_{2,6} + x_{2,7} + x_{2,8} + x_{2,9} + x_{2,10} + x_{2,11} + x_{2,12} + x_{2,13} + x_{2,14} + x_{2,15} + x_{2,16} + x_{2,17} + x_{2,18} + x_{2,19} + x_{2,20} + x_{2,21} + x_{2,22} + x_{2,23} + x_{2,24} + x_{2,25} + x_{2,26} + x_{2,27} + x_{2,28} + x_{2,29} + x_{2,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{2,47} + x_{2,48} + x_{2,49} + x_{2,50} + x_{2,51} + x_{2,52} + x_{2,53} + x_{2,54} + x_{2,55} + x_{2,56} + x_{2,57} + x_{2,58} + x_{2,59} + x_{2,60} + x_{2,61} + x_{2,62} + x_{2,63} + x_{2,64} + x_{2,65} + x_{2,66} + x_{2,67} + x_{2,68} + x_{2,69} + x_{2,70} + x_{2,71} + x_{2,72} + x_{2,73} + x_{2,74} + x_{2,75} + x_{2,76} = 1\\
& x_{3,1} + x_{3,2} + x_{3,3} + x_{3,4} + x_{3,5} + x_{3,6} + x_{3,7} + x_{3,8} + x_{3,9} + x_{3,10} + x_{3,11} + x_{3,12} + x_{3,13} + x_{3,14} + x_{3,15} + x_{3,16} + x_{3,17} + x_{3,18} + x_{3,19} + x_{3,20} + x_{3,21} + x_{3,22} + x_{3,23} + x_{3,24} + x_{3,25} + x_{3,26} + x_{3,27} + x_{3,28} + x_{3,29} + x_{3,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{3,47} + x_{3,48} + x_{3,49} + x_{3,50} + x_{3,51} + x_{3,52} + x_{3,53} + x_{3,54} + x_{3,55} + x_{3,56} + x_{3,57} + x_{3,58} + x_{3,59} + x_{3,60} + x_{3,61} + x_{3,62} + x_{3,63} + x_{3,64} + x_{3,65} + x_{3,66} + x_{3,67} + x_{3,68} + x_{3,69} + x_{3,70} + x_{3,71} + x_{3,72} + x_{3,73} + x_{3,74} + x_{3,75} + x_{3,76} = 1\\
& x_{4,1} + x_{4,2} + x_{4,3} + x_{4,4} + x_{4,5} + x_{4,6} + x_{4,7} + x_{4,8} + x_{4,9} + x_{4,10} + x_{4,11} + x_{4,12} + x_{4,13} + x_{4,14} + x_{4,15} + x_{4,16} + x_{4,17} + x_{4,18} + x_{4,19} + x_{4,20} + x_{4,21} + x_{4,22} + x_{4,23} + x_{4,24} + x_{4,25} + x_{4,26} + x_{4,27} + x_{4,28} + x_{4,29} + x_{4,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{4,47} + x_{4,48} + x_{4,49} + x_{4,50} + x_{4,51} + x_{4,52} + x_{4,53} + x_{4,54} + x_{4,55} + x_{4,56} + x_{4,57} + x_{4,58} + x_{4,59} + x_{4,60} + x_{4,61} + x_{4,62} + x_{4,63} + x_{4,64} + x_{4,65} + x_{4,66} + x_{4,67} + x_{4,68} + x_{4,69} + x_{4,70} + x_{4,71} + x_{4,72} + x_{4,73} + x_{4,74} + x_{4,75} + x_{4,76} = 1\\
& x_{5,1} + x_{5,2} + x_{5,3} + x_{5,4} + x_{5,5} + x_{5,6} + x_{5,7} + x_{5,8} + x_{5,9} + x_{5,10} + x_{5,11} + x_{5,12} + x_{5,13} + x_{5,14} + x_{5,15} + x_{5,16} + x_{5,17} + x_{5,18} + x_{5,19} + x_{5,20} + x_{5,21} + x_{5,22} + x_{5,23} + x_{5,24} + x_{5,25} + x_{5,26} + x_{5,27} + x_{5,28} + x_{5,29} + x_{5,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{5,47} + x_{5,48} + x_{5,49} + x_{5,50} + x_{5,51} + x_{5,52} + x_{5,53} + x_{5,54} + x_{5,55} + x_{5,56} + x_{5,57} + x_{5,58} + x_{5,59} + x_{5,60} + x_{5,61} + x_{5,62} + x_{5,63} + x_{5,64} + x_{5,65} + x_{5,66} + x_{5,67} + x_{5,68} + x_{5,69} + x_{5,70} + x_{5,71} + x_{5,72} + x_{5,73} + x_{5,74} + x_{5,75} + x_{5,76} = 1\\
& x_{6,1} + x_{6,2} + x_{6,3} + x_{6,4} + x_{6,5} + x_{6,6} + x_{6,7} + x_{6,8} + x_{6,9} + x_{6,10} + x_{6,11} + x_{6,12} + x_{6,13} + x_{6,14} + x_{6,15} + x_{6,16} + x_{6,17} + x_{6,18} + x_{6,19} + x_{6,20} + x_{6,21} + x_{6,22} + x_{6,23} + x_{6,24} + x_{6,25} + x_{6,26} + x_{6,27} + x_{6,28} + x_{6,29} + x_{6,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{6,47} + x_{6,48} + x_{6,49} + x_{6,50} + x_{6,51} + x_{6,52} + x_{6,53} + x_{6,54} + x_{6,55} + x_{6,56} + x_{6,57} + x_{6,58} + x_{6,59} + x_{6,60} + x_{6,61} + x_{6,62} + x_{6,63} + x_{6,64} + x_{6,65} + x_{6,66} + x_{6,67} + x_{6,68} + x_{6,69} + x_{6,70} + x_{6,71} + x_{6,72} + x_{6,73} + x_{6,74} + x_{6,75} + x_{6,76} = 1\\
& x_{7,1} + x_{7,2} + x_{7,3} + x_{7,4} + x_{7,5} + x_{7,6} + x_{7,7} + x_{7,8} + x_{7,9} + x_{7,10} + x_{7,11} + x_{7,12} + x_{7,13} + x_{7,14} + x_{7,15} + x_{7,16} + x_{7,17} + x_{7,18} + x_{7,19} + x_{7,20} + x_{7,21} + x_{7,22} + x_{7,23} + x_{7,24} + x_{7,25} + x_{7,26} + x_{7,27} + x_{7,28} + x_{7,29} + x_{7,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{7,47} + x_{7,48} + x_{7,49} + x_{7,50} + x_{7,51} + x_{7,52} + x_{7,53} + x_{7,54} + x_{7,55} + x_{7,56} + x_{7,57} + x_{7,58} + x_{7,59} + x_{7,60} + x_{7,61} + x_{7,62} + x_{7,63} + x_{7,64} + x_{7,65} + x_{7,66} + x_{7,67} + x_{7,68} + x_{7,69} + x_{7,70} + x_{7,71} + x_{7,72} + x_{7,73} + x_{7,74} + x_{7,75} + x_{7,76} = 1\\
& x_{8,1} + x_{8,2} + x_{8,3} + x_{8,4} + x_{8,5} + x_{8,6} + x_{8,7} + x_{8,8} + x_{8,9} + x_{8,10} + x_{8,11} + x_{8,12} + x_{8,13} + x_{8,14} + x_{8,15} + x_{8,16} + x_{8,17} + x_{8,18} + x_{8,19} + x_{8,20} + x_{8,21} + x_{8,22} + x_{8,23} + x_{8,24} + x_{8,25} + x_{8,26} + x_{8,27} + x_{8,28} + x_{8,29} + x_{8,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{8,47} + x_{8,48} + x_{8,49} + x_{8,50} + x_{8,51} + x_{8,52} + x_{8,53} + x_{8,54} + x_{8,55} + x_{8,56} + x_{8,57} + x_{8,58} + x_{8,59} + x_{8,60} + x_{8,61} + x_{8,62} + x_{8,63} + x_{8,64} + x_{8,65} + x_{8,66} + x_{8,67} + x_{8,68} + x_{8,69} + x_{8,70} + x_{8,71} + x_{8,72} + x_{8,73} + x_{8,74} + x_{8,75} + x_{8,76} = 1\\
& x_{9,1} + x_{9,2} + x_{9,3} + x_{9,4} + x_{9,5} + x_{9,6} + x_{9,7} + x_{9,8} + x_{9,9} + x_{9,10} + x_{9,11} + x_{9,12} + x_{9,13} + x_{9,14} + x_{9,15} + x_{9,16} + x_{9,17} + x_{9,18} + x_{9,19} + x_{9,20} + x_{9,21} + x_{9,22} + x_{9,23} + x_{9,24} + x_{9,25} + x_{9,26} + x_{9,27} + x_{9,28} + x_{9,29} + x_{9,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{9,47} + x_{9,48} + x_{9,49} + x_{9,50} + x_{9,51} + x_{9,52} + x_{9,53} + x_{9,54} + x_{9,55} + x_{9,56} + x_{9,57} + x_{9,58} + x_{9,59} + x_{9,60} + x_{9,61} + x_{9,62} + x_{9,63} + x_{9,64} + x_{9,65} + x_{9,66} + x_{9,67} + x_{9,68} + x_{9,69} + x_{9,70} + x_{9,71} + x_{9,72} + x_{9,73} + x_{9,74} + x_{9,75} + x_{9,76} = 1\\
& x_{10,1} + x_{10,2} + x_{10,3} + x_{10,4} + x_{10,5} + x_{10,6} + x_{10,7} + x_{10,8} + x_{10,9} + x_{10,10} + x_{10,11} + x_{10,12} + x_{10,13} + x_{10,14} + x_{10,15} + x_{10,16} + x_{10,17} + x_{10,18} + x_{10,19} + x_{10,20} + x_{10,21} + x_{10,22} + x_{10,23} + x_{10,24} + x_{10,25} + x_{10,26} + x_{10,27} + x_{10,28} + x_{10,29} + x_{10,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{10,47} + x_{10,48} + x_{10,49} + x_{10,50} + x_{10,51} + x_{10,52} + x_{10,53} + x_{10,54} + x_{10,55} + x_{10,56} + x_{10,57} + x_{10,58} + x_{10,59} + x_{10,60} + x_{10,61} + x_{10,62} + x_{10,63} + x_{10,64} + x_{10,65} + x_{10,66} + x_{10,67} + x_{10,68} + x_{10,69} + x_{10,70} + x_{10,71} + x_{10,72} + x_{10,73} + x_{10,74} + x_{10,75} + x_{10,76} = 1\\
& x_{11,1} + x_{11,2} + x_{11,3} + x_{11,4} + x_{11,5} + x_{11,6} + x_{11,7} + x_{11,8} + x_{11,9} + x_{11,10} + x_{11,11} + x_{11,12} + x_{11,13} + x_{11,14} + x_{11,15} + x_{11,16} + x_{11,17} + x_{11,18} + x_{11,19} + x_{11,20} + x_{11,21} + x_{11,22} + x_{11,23} + x_{11,24} + x_{11,25} + x_{11,26} + x_{11,27} + x_{11,28} + x_{11,29} + x_{11,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{11,47} + x_{11,48} + x_{11,49} + x_{11,50} + x_{11,51} + x_{11,52} + x_{11,53} + x_{11,54} + x_{11,55} + x_{11,56} + x_{11,57} + x_{11,58} + x_{11,59} + x_{11,60} + x_{11,61} + x_{11,62} + x_{11,63} + x_{11,64} + x_{11,65} + x_{11,66} + x_{11,67} + x_{11,68} + x_{11,69} + x_{11,70} + x_{11,71} + x_{11,72} + x_{11,73} + x_{11,74} + x_{11,75} + x_{11,76} = 1\\
& x_{12,1} + x_{12,2} + x_{12,3} + x_{12,4} + x_{12,5} + x_{12,6} + x_{12,7} + x_{12,8} + x_{12,9} + x_{12,10} + x_{12,11} + x_{12,12} + x_{12,13} + x_{12,14} + x_{12,15} + x_{12,16} + x_{12,17} + x_{12,18} + x_{12,19} + x_{12,20} + x_{12,21} + x_{12,22} + x_{12,23} + x_{12,24} + x_{12,25} + x_{12,26} + x_{12,27} + x_{12,28} + x_{12,29} + x_{12,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{12,47} + x_{12,48} + x_{12,49} + x_{12,50} + x_{12,51} + x_{12,52} + x_{12,53} + x_{12,54} + x_{12,55} + x_{12,56} + x_{12,57} + x_{12,58} + x_{12,59} + x_{12,60} + x_{12,61} + x_{12,62} + x_{12,63} + x_{12,64} + x_{12,65} + x_{12,66} + x_{12,67} + x_{12,68} + x_{12,69} + x_{12,70} + x_{12,71} + x_{12,72} + x_{12,73} + x_{12,74} + x_{12,75} + x_{12,76} = 1\\
& x_{13,1} + x_{13,2} + x_{13,3} + x_{13,4} + x_{13,5} + x_{13,6} + x_{13,7} + x_{13,8} + x_{13,9} + x_{13,10} + x_{13,11} + x_{13,12} + x_{13,13} + x_{13,14} + x_{13,15} + x_{13,16} + x_{13,17} + x_{13,18} + x_{13,19} + x_{13,20} + x_{13,21} + x_{13,22} + x_{13,23} + x_{13,24} + x_{13,25} + x_{13,26} + x_{13,27} + x_{13,28} + x_{13,29} + x_{13,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{13,47} + x_{13,48} + x_{13,49} + x_{13,50} + x_{13,51} + x_{13,52} + x_{13,53} + x_{13,54} + x_{13,55} + x_{13,56} + x_{13,57} + x_{13,58} + x_{13,59} + x_{13,60} + x_{13,61} + x_{13,62} + x_{13,63} + x_{13,64} + x_{13,65} + x_{13,66} + x_{13,67} + x_{13,68} + x_{13,69} + x_{13,70} + x_{13,71} + x_{13,72} + x_{13,73} + x_{13,74} + x_{13,75} + x_{13,76} = 1\\
& x_{14,1} + x_{14,2} + x_{14,3} + x_{14,4} + x_{14,5} + x_{14,6} + x_{14,7} + x_{14,8} + x_{14,9} + x_{14,10} + x_{14,11} + x_{14,12} + x_{14,13} + x_{14,14} + x_{14,15} + x_{14,16} + x_{14,17} + x_{14,18} + x_{14,19} + x_{14,20} + x_{14,21} + x_{14,22} + x_{14,23} + x_{14,24} + x_{14,25} + x_{14,26} + x_{14,27} + x_{14,28} + x_{14,29} + x_{14,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{14,47} + x_{14,48} + x_{14,49} + x_{14,50} + x_{14,51} + x_{14,52} + x_{14,53} + x_{14,54} + x_{14,55} + x_{14,56} + x_{14,57} + x_{14,58} + x_{14,59} + x_{14,60} + x_{14,61} + x_{14,62} + x_{14,63} + x_{14,64} + x_{14,65} + x_{14,66} + x_{14,67} + x_{14,68} + x_{14,69} + x_{14,70} + x_{14,71} + x_{14,72} + x_{14,73} + x_{14,74} + x_{14,75} + x_{14,76} = 1\\
& x_{15,1} + x_{15,2} + x_{15,3} + x_{15,4} + x_{15,5} + x_{15,6} + x_{15,7} + x_{15,8} + x_{15,9} + x_{15,10} + x_{15,11} + x_{15,12} + x_{15,13} + x_{15,14} + x_{15,15} + x_{15,16} + x_{15,17} + x_{15,18} + x_{15,19} + x_{15,20} + x_{15,21} + x_{15,22} + x_{15,23} + x_{15,24} + x_{15,25} + x_{15,26} + x_{15,27} + x_{15,28} + x_{15,29} + x_{15,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{15,47} + x_{15,48} + x_{15,49} + x_{15,50} + x_{15,51} + x_{15,52} + x_{15,53} + x_{15,54} + x_{15,55} + x_{15,56} + x_{15,57} + x_{15,58} + x_{15,59} + x_{15,60} + x_{15,61} + x_{15,62} + x_{15,63} + x_{15,64} + x_{15,65} + x_{15,66} + x_{15,67} + x_{15,68} + x_{15,69} + x_{15,70} + x_{15,71} + x_{15,72} + x_{15,73} + x_{15,74} + x_{15,75} + x_{15,76} = 1\\
& x_{16,1} + x_{16,2} + x_{16,3} + x_{16,4} + x_{16,5} + x_{16,6} + x_{16,7} + x_{16,8} + x_{16,9} + x_{16,10} + x_{16,11} + x_{16,12} + x_{16,13} + x_{16,14} + x_{16,15} + x_{16,16} + x_{16,17} + x_{16,18} + x_{16,19} + x_{16,20} + x_{16,21} + x_{16,22} + x_{16,23} + x_{16,24} + x_{16,25} + x_{16,26} + x_{16,27} + x_{16,28} + x_{16,29} + x_{16,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{16,47} + x_{16,48} + x_{16,49} + x_{16,50} + x_{16,51} + x_{16,52} + x_{16,53} + x_{16,54} + x_{16,55} + x_{16,56} + x_{16,57} + x_{16,58} + x_{16,59} + x_{16,60} + x_{16,61} + x_{16,62} + x_{16,63} + x_{16,64} + x_{16,65} + x_{16,66} + x_{16,67} + x_{16,68} + x_{16,69} + x_{16,70} + x_{16,71} + x_{16,72} + x_{16,73} + x_{16,74} + x_{16,75} + x_{16,76} = 1\\
& x_{17,1} + x_{17,2} + x_{17,3} + x_{17,4} + x_{17,5} + x_{17,6} + x_{17,7} + x_{17,8} + x_{17,9} + x_{17,10} + x_{17,11} + x_{17,12} + x_{17,13} + x_{17,14} + x_{17,15} + x_{17,16} + x_{17,17} + x_{17,18} + x_{17,19} + x_{17,20} + x_{17,21} + x_{17,22} + x_{17,23} + x_{17,24} + x_{17,25} + x_{17,26} + x_{17,27} + x_{17,28} + x_{17,29} + x_{17,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{17,47} + x_{17,48} + x_{17,49} + x_{17,50} + x_{17,51} + x_{17,52} + x_{17,53} + x_{17,54} + x_{17,55} + x_{17,56} + x_{17,57} + x_{17,58} + x_{17,59} + x_{17,60} + x_{17,61} + x_{17,62} + x_{17,63} + x_{17,64} + x_{17,65} + x_{17,66} + x_{17,67} + x_{17,68} + x_{17,69} + x_{17,70} + x_{17,71} + x_{17,72} + x_{17,73} + x_{17,74} + x_{17,75} + x_{17,76} = 1\\
& x_{18,1} + x_{18,2} + x_{18,3} + x_{18,4} + x_{18,5} + x_{18,6} + x_{18,7} + x_{18,8} + x_{18,9} + x_{18,10} + x_{18,11} + x_{18,12} + x_{18,13} + x_{18,14} + x_{18,15} + x_{18,16} + x_{18,17} + x_{18,18} + x_{18,19} + x_{18,20} + x_{18,21} + x_{18,22} + x_{18,23} + x_{18,24} + x_{18,25} + x_{18,26} + x_{18,27} + x_{18,28} + x_{18,29} + x_{18,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{18,47} + x_{18,48} + x_{18,49} + x_{18,50} + x_{18,51} + x_{18,52} + x_{18,53} + x_{18,54} + x_{18,55} + x_{18,56} + x_{18,57} + x_{18,58} + x_{18,59} + x_{18,60} + x_{18,61} + x_{18,62} + x_{18,63} + x_{18,64} + x_{18,65} + x_{18,66} + x_{18,67} + x_{18,68} + x_{18,69} + x_{18,70} + x_{18,71} + x_{18,72} + x_{18,73} + x_{18,74} + x_{18,75} + x_{18,76} = 1\\
& x_{19,1} + x_{19,2} + x_{19,3} + x_{19,4} + x_{19,5} + x_{19,6} + x_{19,7} + x_{19,8} + x_{19,9} + x_{19,10} + x_{19,11} + x_{19,12} + x_{19,13} + x_{19,14} + x_{19,15} + x_{19,16} + x_{19,17} + x_{19,18} + x_{19,19} + x_{19,20} + x_{19,21} + x_{19,22} + x_{19,23} + x_{19,24} + x_{19,25} + x_{19,26} + x_{19,27} + x_{19,28} + x_{19,29} + x_{19,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{19,47} + x_{19,48} + x_{19,49} + x_{19,50} + x_{19,51} + x_{19,52} + x_{19,53} + x_{19,54} + x_{19,55} + x_{19,56} + x_{19,57} + x_{19,58} + x_{19,59} + x_{19,60} + x_{19,61} + x_{19,62} + x_{19,63} + x_{19,64} + x_{19,65} + x_{19,66} + x_{19,67} + x_{19,68} + x_{19,69} + x_{19,70} + x_{19,71} + x_{19,72} + x_{19,73} + x_{19,74} + x_{19,75} + x_{19,76} = 1\\
& x_{20,1} + x_{20,2} + x_{20,3} + x_{20,4} + x_{20,5} + x_{20,6} + x_{20,7} + x_{20,8} + x_{20,9} + x_{20,10} + x_{20,11} + x_{20,12} + x_{20,13} + x_{20,14} + x_{20,15} + x_{20,16} + x_{20,17} + x_{20,18} + x_{20,19} + x_{20,20} + x_{20,21} + x_{20,22} + x_{20,23} + x_{20,24} + x_{20,25} + x_{20,26} + x_{20,27} + x_{20,28} + x_{20,29} + x_{20,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{20,47} + x_{20,48} + x_{20,49} + x_{20,50} + x_{20,51} + x_{20,52} + x_{20,53} + x_{20,54} + x_{20,55} + x_{20,56} + x_{20,57} + x_{20,58} + x_{20,59} + x_{20,60} + x_{20,61} + x_{20,62} + x_{20,63} + x_{20,64} + x_{20,65} + x_{20,66} + x_{20,67} + x_{20,68} + x_{20,69} + x_{20,70} + x_{20,71} + x_{20,72} + x_{20,73} + x_{20,74} + x_{20,75} + x_{20,76} = 1\\
& x_{21,1} + x_{21,2} + x_{21,3} + x_{21,4} + x_{21,5} + x_{21,6} + x_{21,7} + x_{21,8} + x_{21,9} + x_{21,10} + x_{21,11} + x_{21,12} + x_{21,13} + x_{21,14} + x_{21,15} + x_{21,16} + x_{21,17} + x_{21,18} + x_{21,19} + x_{21,20} + x_{21,21} + x_{21,22} + x_{21,23} + x_{21,24} + x_{21,25} + x_{21,26} + x_{21,27} + x_{21,28} + x_{21,29} + x_{21,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{21,47} + x_{21,48} + x_{21,49} + x_{21,50} + x_{21,51} + x_{21,52} + x_{21,53} + x_{21,54} + x_{21,55} + x_{21,56} + x_{21,57} + x_{21,58} + x_{21,59} + x_{21,60} + x_{21,61} + x_{21,62} + x_{21,63} + x_{21,64} + x_{21,65} + x_{21,66} + x_{21,67} + x_{21,68} + x_{21,69} + x_{21,70} + x_{21,71} + x_{21,72} + x_{21,73} + x_{21,74} + x_{21,75} + x_{21,76} = 1\\
& x_{22,1} + x_{22,2} + x_{22,3} + x_{22,4} + x_{22,5} + x_{22,6} + x_{22,7} + x_{22,8} + x_{22,9} + x_{22,10} + x_{22,11} + x_{22,12} + x_{22,13} + x_{22,14} + x_{22,15} + x_{22,16} + x_{22,17} + x_{22,18} + x_{22,19} + x_{22,20} + x_{22,21} + x_{22,22} + x_{22,23} + x_{22,24} + x_{22,25} + x_{22,26} + x_{22,27} + x_{22,28} + x_{22,29} + x_{22,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{22,47} + x_{22,48} + x_{22,49} + x_{22,50} + x_{22,51} + x_{22,52} + x_{22,53} + x_{22,54} + x_{22,55} + x_{22,56} + x_{22,57} + x_{22,58} + x_{22,59} + x_{22,60} + x_{22,61} + x_{22,62} + x_{22,63} + x_{22,64} + x_{22,65} + x_{22,66} + x_{22,67} + x_{22,68} + x_{22,69} + x_{22,70} + x_{22,71} + x_{22,72} + x_{22,73} + x_{22,74} + x_{22,75} + x_{22,76} = 1\\
& x_{23,1} + x_{23,2} + x_{23,3} + x_{23,4} + x_{23,5} + x_{23,6} + x_{23,7} + x_{23,8} + x_{23,9} + x_{23,10} + x_{23,11} + x_{23,12} + x_{23,13} + x_{23,14} + x_{23,15} + x_{23,16} + x_{23,17} + x_{23,18} + x_{23,19} + x_{23,20} + x_{23,21} + x_{23,22} + x_{23,23} + x_{23,24} + x_{23,25} + x_{23,26} + x_{23,27} + x_{23,28} + x_{23,29} + x_{23,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{23,47} + x_{23,48} + x_{23,49} + x_{23,50} + x_{23,51} + x_{23,52} + x_{23,53} + x_{23,54} + x_{23,55} + x_{23,56} + x_{23,57} + x_{23,58} + x_{23,59} + x_{23,60} + x_{23,61} + x_{23,62} + x_{23,63} + x_{23,64} + x_{23,65} + x_{23,66} + x_{23,67} + x_{23,68} + x_{23,69} + x_{23,70} + x_{23,71} + x_{23,72} + x_{23,73} + x_{23,74} + x_{23,75} + x_{23,76} = 1\\
& x_{24,1} + x_{24,2} + x_{24,3} + x_{24,4} + x_{24,5} + x_{24,6} + x_{24,7} + x_{24,8} + x_{24,9} + x_{24,10} + x_{24,11} + x_{24,12} + x_{24,13} + x_{24,14} + x_{24,15} + x_{24,16} + x_{24,17} + x_{24,18} + x_{24,19} + x_{24,20} + x_{24,21} + x_{24,22} + x_{24,23} + x_{24,24} + x_{24,25} + x_{24,26} + x_{24,27} + x_{24,28} + x_{24,29} + x_{24,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{24,47} + x_{24,48} + x_{24,49} + x_{24,50} + x_{24,51} + x_{24,52} + x_{24,53} + x_{24,54} + x_{24,55} + x_{24,56} + x_{24,57} + x_{24,58} + x_{24,59} + x_{24,60} + x_{24,61} + x_{24,62} + x_{24,63} + x_{24,64} + x_{24,65} + x_{24,66} + x_{24,67} + x_{24,68} + x_{24,69} + x_{24,70} + x_{24,71} + x_{24,72} + x_{24,73} + x_{24,74} + x_{24,75} + x_{24,76} = 1\\
& x_{25,1} + x_{25,2} + x_{25,3} + x_{25,4} + x_{25,5} + x_{25,6} + x_{25,7} + x_{25,8} + x_{25,9} + x_{25,10} + x_{25,11} + x_{25,12} + x_{25,13} + x_{25,14} + x_{25,15} + x_{25,16} + x_{25,17} + x_{25,18} + x_{25,19} + x_{25,20} + x_{25,21} + x_{25,22} + x_{25,23} + x_{25,24} + x_{25,25} + x_{25,26} + x_{25,27} + x_{25,28} + x_{25,29} + x_{25,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{25,47} + x_{25,48} + x_{25,49} + x_{25,50} + x_{25,51} + x_{25,52} + x_{25,53} + x_{25,54} + x_{25,55} + x_{25,56} + x_{25,57} + x_{25,58} + x_{25,59} + x_{25,60} + x_{25,61} + x_{25,62} + x_{25,63} + x_{25,64} + x_{25,65} + x_{25,66} + x_{25,67} + x_{25,68} + x_{25,69} + x_{25,70} + x_{25,71} + x_{25,72} + x_{25,73} + x_{25,74} + x_{25,75} + x_{25,76} = 1\\
& x_{26,1} + x_{26,2} + x_{26,3} + x_{26,4} + x_{26,5} + x_{26,6} + x_{26,7} + x_{26,8} + x_{26,9} + x_{26,10} + x_{26,11} + x_{26,12} + x_{26,13} + x_{26,14} + x_{26,15} + x_{26,16} + x_{26,17} + x_{26,18} + x_{26,19} + x_{26,20} + x_{26,21} + x_{26,22} + x_{26,23} + x_{26,24} + x_{26,25} + x_{26,26} + x_{26,27} + x_{26,28} + x_{26,29} + x_{26,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{26,47} + x_{26,48} + x_{26,49} + x_{26,50} + x_{26,51} + x_{26,52} + x_{26,53} + x_{26,54} + x_{26,55} + x_{26,56} + x_{26,57} + x_{26,58} + x_{26,59} + x_{26,60} + x_{26,61} + x_{26,62} + x_{26,63} + x_{26,64} + x_{26,65} + x_{26,66} + x_{26,67} + x_{26,68} + x_{26,69} + x_{26,70} + x_{26,71} + x_{26,72} + x_{26,73} + x_{26,74} + x_{26,75} + x_{26,76} = 1\\
& x_{27,1} + x_{27,2} + x_{27,3} + x_{27,4} + x_{27,5} + x_{27,6} + x_{27,7} + x_{27,8} + x_{27,9} + x_{27,10} + x_{27,11} + x_{27,12} + x_{27,13} + x_{27,14} + x_{27,15} + x_{27,16} + x_{27,17} + x_{27,18} + x_{27,19} + x_{27,20} + x_{27,21} + x_{27,22} + x_{27,23} + x_{27,24} + x_{27,25} + x_{27,26} + x_{27,27} + x_{27,28} + x_{27,29} + x_{27,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{27,47} + x_{27,48} + x_{27,49} + x_{27,50} + x_{27,51} + x_{27,52} + x_{27,53} + x_{27,54} + x_{27,55} + x_{27,56} + x_{27,57} + x_{27,58} + x_{27,59} + x_{27,60} + x_{27,61} + x_{27,62} + x_{27,63} + x_{27,64} + x_{27,65} + x_{27,66} + x_{27,67} + x_{27,68} + x_{27,69} + x_{27,70} + x_{27,71} + x_{27,72} + x_{27,73} + x_{27,74} + x_{27,75} + x_{27,76} = 1\\
& x_{28,1} + x_{28,2} + x_{28,3} + x_{28,4} + x_{28,5} + x_{28,6} + x_{28,7} + x_{28,8} + x_{28,9} + x_{28,10} + x_{28,11} + x_{28,12} + x_{28,13} + x_{28,14} + x_{28,15} + x_{28,16} + x_{28,17} + x_{28,18} + x_{28,19} + x_{28,20} + x_{28,21} + x_{28,22} + x_{28,23} + x_{28,24} + x_{28,25} + x_{28,26} + x_{28,27} + x_{28,28} + x_{28,29} + x_{28,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{28,47} + x_{28,48} + x_{28,49} + x_{28,50} + x_{28,51} + x_{28,52} + x_{28,53} + x_{28,54} + x_{28,55} + x_{28,56} + x_{28,57} + x_{28,58} + x_{28,59} + x_{28,60} + x_{28,61} + x_{28,62} + x_{28,63} + x_{28,64} + x_{28,65} + x_{28,66} + x_{28,67} + x_{28,68} + x_{28,69} + x_{28,70} + x_{28,71} + x_{28,72} + x_{28,73} + x_{28,74} + x_{28,75} + x_{28,76} = 1\\
& x_{29,1} + x_{29,2} + x_{29,3} + x_{29,4} + x_{29,5} + x_{29,6} + x_{29,7} + x_{29,8} + x_{29,9} + x_{29,10} + x_{29,11} + x_{29,12} + x_{29,13} + x_{29,14} + x_{29,15} + x_{29,16} + x_{29,17} + x_{29,18} + x_{29,19} + x_{29,20} + x_{29,21} + x_{29,22} + x_{29,23} + x_{29,24} + x_{29,25} + x_{29,26} + x_{29,27} + x_{29,28} + x_{29,29} + x_{29,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{29,47} + x_{29,48} + x_{29,49} + x_{29,50} + x_{29,51} + x_{29,52} + x_{29,53} + x_{29,54} + x_{29,55} + x_{29,56} + x_{29,57} + x_{29,58} + x_{29,59} + x_{29,60} + x_{29,61} + x_{29,62} + x_{29,63} + x_{29,64} + x_{29,65} + x_{29,66} + x_{29,67} + x_{29,68} + x_{29,69} + x_{29,70} + x_{29,71} + x_{29,72} + x_{29,73} + x_{29,74} + x_{29,75} + x_{29,76} = 1\\
& x_{30,1} + x_{30,2} + x_{30,3} + x_{30,4} + x_{30,5} + x_{30,6} + x_{30,7} + x_{30,8} + x_{30,9} + x_{30,10} + x_{30,11} + x_{30,12} + x_{30,13} + x_{30,14} + x_{30,15} + x_{30,16} + x_{30,17} + x_{30,18} + x_{30,19} + x_{30,20} + x_{30,21} + x_{30,22} + x_{30,23} + x_{30,24} + x_{30,25} + x_{30,26} + x_{30,27} + x_{30,28} + x_{30,29} + x_{30,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{30,47} + x_{30,48} + x_{30,49} + x_{30,50} + x_{30,51} + x_{30,52} + x_{30,53} + x_{30,54} + x_{30,55} + x_{30,56} + x_{30,57} + x_{30,58} + x_{30,59} + x_{30,60} + x_{30,61} + x_{30,62} + x_{30,63} + x_{30,64} + x_{30,65} + x_{30,66} + x_{30,67} + x_{30,68} + x_{30,69} + x_{30,70} + x_{30,71} + x_{30,72} + x_{30,73} + x_{30,74} + x_{30,75} + x_{30,76} = 1\\
& x_{31,1} + x_{31,2} + x_{31,3} + x_{31,4} + x_{31,5} + x_{31,6} + x_{31,7} + x_{31,8} + x_{31,9} + x_{31,10} + x_{31,11} + x_{31,12} + x_{31,13} + x_{31,14} + x_{31,15} + x_{31,16} + x_{31,17} + x_{31,18} + x_{31,19} + x_{31,20} + x_{31,21} + x_{31,22} + x_{31,23} + x_{31,24} + x_{31,25} + x_{31,26} + x_{31,27} + x_{31,28} + x_{31,29} + x_{31,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{31,47} + x_{31,48} + x_{31,49} + x_{31,50} + x_{31,51} + x_{31,52} + x_{31,53} + x_{31,54} + x_{31,55} + x_{31,56} + x_{31,57} + x_{31,58} + x_{31,59} + x_{31,60} + x_{31,61} + x_{31,62} + x_{31,63} + x_{31,64} + x_{31,65} + x_{31,66} + x_{31,67} + x_{31,68} + x_{31,69} + x_{31,70} + x_{31,71} + x_{31,72} + x_{31,73} + x_{31,74} + x_{31,75} + x_{31,76} = 1\\
& x_{32,1} + x_{32,2} + x_{32,3} + x_{32,4} + x_{32,5} + x_{32,6} + x_{32,7} + x_{32,8} + x_{32,9} + x_{32,10} + x_{32,11} + x_{32,12} + x_{32,13} + x_{32,14} + x_{32,15} + x_{32,16} + x_{32,17} + x_{32,18} + x_{32,19} + x_{32,20} + x_{32,21} + x_{32,22} + x_{32,23} + x_{32,24} + x_{32,25} + x_{32,26} + x_{32,27} + x_{32,28} + x_{32,29} + x_{32,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{32,47} + x_{32,48} + x_{32,49} + x_{32,50} + x_{32,51} + x_{32,52} + x_{32,53} + x_{32,54} + x_{32,55} + x_{32,56} + x_{32,57} + x_{32,58} + x_{32,59} + x_{32,60} + x_{32,61} + x_{32,62} + x_{32,63} + x_{32,64} + x_{32,65} + x_{32,66} + x_{32,67} + x_{32,68} + x_{32,69} + x_{32,70} + x_{32,71} + x_{32,72} + x_{32,73} + x_{32,74} + x_{32,75} + x_{32,76} = 1\\
& x_{33,1} + x_{33,2} + x_{33,3} + x_{33,4} + x_{33,5} + x_{33,6} + x_{33,7} + x_{33,8} + x_{33,9} + x_{33,10} + x_{33,11} + x_{33,12} + x_{33,13} + x_{33,14} + x_{33,15} + x_{33,16} + x_{33,17} + x_{33,18} + x_{33,19} + x_{33,20} + x_{33,21} + x_{33,22} + x_{33,23} + x_{33,24} + x_{33,25} + x_{33,26} + x_{33,27} + x_{33,28} + x_{33,29} + x_{33,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{33,47} + x_{33,48} + x_{33,49} + x_{33,50} + x_{33,51} + x_{33,52} + x_{33,53} + x_{33,54} + x_{33,55} + x_{33,56} + x_{33,57} + x_{33,58} + x_{33,59} + x_{33,60} + x_{33,61} + x_{33,62} + x_{33,63} + x_{33,64} + x_{33,65} + x_{33,66} + x_{33,67} + x_{33,68} + x_{33,69} + x_{33,70} + x_{33,71} + x_{33,72} + x_{33,73} + x_{33,74} + x_{33,75} + x_{33,76} = 1\\
& x_{34,1} + x_{34,2} + x_{34,3} + x_{34,4} + x_{34,5} + x_{34,6} + x_{34,7} + x_{34,8} + x_{34,9} + x_{34,10} + x_{34,11} + x_{34,12} + x_{34,13} + x_{34,14} + x_{34,15} + x_{34,16} + x_{34,17} + x_{34,18} + x_{34,19} + x_{34,20} + x_{34,21} + x_{34,22} + x_{34,23} + x_{34,24} + x_{34,25} + x_{34,26} + x_{34,27} + x_{34,28} + x_{34,29} + x_{34,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{34,47} + x_{34,48} + x_{34,49} + x_{34,50} + x_{34,51} + x_{34,52} + x_{34,53} + x_{34,54} + x_{34,55} + x_{34,56} + x_{34,57} + x_{34,58} + x_{34,59} + x_{34,60} + x_{34,61} + x_{34,62} + x_{34,63} + x_{34,64} + x_{34,65} + x_{34,66} + x_{34,67} + x_{34,68} + x_{34,69} + x_{34,70} + x_{34,71} + x_{34,72} + x_{34,73} + x_{34,74} + x_{34,75} + x_{34,76} = 1\\
& x_{35,1} + x_{35,2} + x_{35,3} + x_{35,4} + x_{35,5} + x_{35,6} + x_{35,7} + x_{35,8} + x_{35,9} + x_{35,10} + x_{35,11} + x_{35,12} + x_{35,13} + x_{35,14} + x_{35,15} + x_{35,16} + x_{35,17} + x_{35,18} + x_{35,19} + x_{35,20} + x_{35,21} + x_{35,22} + x_{35,23} + x_{35,24} + x_{35,25} + x_{35,26} + x_{35,27} + x_{35,28} + x_{35,29} + x_{35,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{35,47} + x_{35,48} + x_{35,49} + x_{35,50} + x_{35,51} + x_{35,52} + x_{35,53} + x_{35,54} + x_{35,55} + x_{35,56} + x_{35,57} + x_{35,58} + x_{35,59} + x_{35,60} + x_{35,61} + x_{35,62} + x_{35,63} + x_{35,64} + x_{35,65} + x_{35,66} + x_{35,67} + x_{35,68} + x_{35,69} + x_{35,70} + x_{35,71} + x_{35,72} + x_{35,73} + x_{35,74} + x_{35,75} + x_{35,76} = 1\\
& x_{36,1} + x_{36,2} + x_{36,3} + x_{36,4} + x_{36,5} + x_{36,6} + x_{36,7} + x_{36,8} + x_{36,9} + x_{36,10} + x_{36,11} + x_{36,12} + x_{36,13} + x_{36,14} + x_{36,15} + x_{36,16} + x_{36,17} + x_{36,18} + x_{36,19} + x_{36,20} + x_{36,21} + x_{36,22} + x_{36,23} + x_{36,24} + x_{36,25} + x_{36,26} + x_{36,27} + x_{36,28} + x_{36,29} + x_{36,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{36,47} + x_{36,48} + x_{36,49} + x_{36,50} + x_{36,51} + x_{36,52} + x_{36,53} + x_{36,54} + x_{36,55} + x_{36,56} + x_{36,57} + x_{36,58} + x_{36,59} + x_{36,60} + x_{36,61} + x_{36,62} + x_{36,63} + x_{36,64} + x_{36,65} + x_{36,66} + x_{36,67} + x_{36,68} + x_{36,69} + x_{36,70} + x_{36,71} + x_{36,72} + x_{36,73} + x_{36,74} + x_{36,75} + x_{36,76} = 1\\
& x_{37,1} + x_{37,2} + x_{37,3} + x_{37,4} + x_{37,5} + x_{37,6} + x_{37,7} + x_{37,8} + x_{37,9} + x_{37,10} + x_{37,11} + x_{37,12} + x_{37,13} + x_{37,14} + x_{37,15} + x_{37,16} + x_{37,17} + x_{37,18} + x_{37,19} + x_{37,20} + x_{37,21} + x_{37,22} + x_{37,23} + x_{37,24} + x_{37,25} + x_{37,26} + x_{37,27} + x_{37,28} + x_{37,29} + x_{37,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{37,47} + x_{37,48} + x_{37,49} + x_{37,50} + x_{37,51} + x_{37,52} + x_{37,53} + x_{37,54} + x_{37,55} + x_{37,56} + x_{37,57} + x_{37,58} + x_{37,59} + x_{37,60} + x_{37,61} + x_{37,62} + x_{37,63} + x_{37,64} + x_{37,65} + x_{37,66} + x_{37,67} + x_{37,68} + x_{37,69} + x_{37,70} + x_{37,71} + x_{37,72} + x_{37,73} + x_{37,74} + x_{37,75} + x_{37,76} = 1\\
& x_{38,1} + x_{38,2} + x_{38,3} + x_{38,4} + x_{38,5} + x_{38,6} + x_{38,7} + x_{38,8} + x_{38,9} + x_{38,10} + x_{38,11} + x_{38,12} + x_{38,13} + x_{38,14} + x_{38,15} + x_{38,16} + x_{38,17} + x_{38,18} + x_{38,19} + x_{38,20} + x_{38,21} + x_{38,22} + x_{38,23} + x_{38,24} + x_{38,25} + x_{38,26} + x_{38,27} + x_{38,28} + x_{38,29} + x_{38,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{38,47} + x_{38,48} + x_{38,49} + x_{38,50} + x_{38,51} + x_{38,52} + x_{38,53} + x_{38,54} + x_{38,55} + x_{38,56} + x_{38,57} + x_{38,58} + x_{38,59} + x_{38,60} + x_{38,61} + x_{38,62} + x_{38,63} + x_{38,64} + x_{38,65} + x_{38,66} + x_{38,67} + x_{38,68} + x_{38,69} + x_{38,70} + x_{38,71} + x_{38,72} + x_{38,73} + x_{38,74} + x_{38,75} + x_{38,76} = 1\\
& x_{39,1} + x_{39,2} + x_{39,3} + x_{39,4} + x_{39,5} + x_{39,6} + x_{39,7} + x_{39,8} + x_{39,9} + x_{39,10} + x_{39,11} + x_{39,12} + x_{39,13} + x_{39,14} + x_{39,15} + x_{39,16} + x_{39,17} + x_{39,18} + x_{39,19} + x_{39,20} + x_{39,21} + x_{39,22} + x_{39,23} + x_{39,24} + x_{39,25} + x_{39,26} + x_{39,27} + x_{39,28} + x_{39,29} + x_{39,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{39,47} + x_{39,48} + x_{39,49} + x_{39,50} + x_{39,51} + x_{39,52} + x_{39,53} + x_{39,54} + x_{39,55} + x_{39,56} + x_{39,57} + x_{39,58} + x_{39,59} + x_{39,60} + x_{39,61} + x_{39,62} + x_{39,63} + x_{39,64} + x_{39,65} + x_{39,66} + x_{39,67} + x_{39,68} + x_{39,69} + x_{39,70} + x_{39,71} + x_{39,72} + x_{39,73} + x_{39,74} + x_{39,75} + x_{39,76} = 1\\
& x_{40,1} + x_{40,2} + x_{40,3} + x_{40,4} + x_{40,5} + x_{40,6} + x_{40,7} + x_{40,8} + x_{40,9} + x_{40,10} + x_{40,11} + x_{40,12} + x_{40,13} + x_{40,14} + x_{40,15} + x_{40,16} + x_{40,17} + x_{40,18} + x_{40,19} + x_{40,20} + x_{40,21} + x_{40,22} + x_{40,23} + x_{40,24} + x_{40,25} + x_{40,26} + x_{40,27} + x_{40,28} + x_{40,29} + x_{40,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{40,47} + x_{40,48} + x_{40,49} + x_{40,50} + x_{40,51} + x_{40,52} + x_{40,53} + x_{40,54} + x_{40,55} + x_{40,56} + x_{40,57} + x_{40,58} + x_{40,59} + x_{40,60} + x_{40,61} + x_{40,62} + x_{40,63} + x_{40,64} + x_{40,65} + x_{40,66} + x_{40,67} + x_{40,68} + x_{40,69} + x_{40,70} + x_{40,71} + x_{40,72} + x_{40,73} + x_{40,74} + x_{40,75} + x_{40,76} = 1\\
& x_{41,1} + x_{41,2} + x_{41,3} + x_{41,4} + x_{41,5} + x_{41,6} + x_{41,7} + x_{41,8} + x_{41,9} + x_{41,10} + x_{41,11} + x_{41,12} + x_{41,13} + x_{41,14} + x_{41,15} + x_{41,16} + x_{41,17} + x_{41,18} + x_{41,19} + x_{41,20} + x_{41,21} + x_{41,22} + x_{41,23} + x_{41,24} + x_{41,25} + x_{41,26} + x_{41,27} + x_{41,28} + x_{41,29} + x_{41,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{41,47} + x_{41,48} + x_{41,49} + x_{41,50} + x_{41,51} + x_{41,52} + x_{41,53} + x_{41,54} + x_{41,55} + x_{41,56} + x_{41,57} + x_{41,58} + x_{41,59} + x_{41,60} + x_{41,61} + x_{41,62} + x_{41,63} + x_{41,64} + x_{41,65} + x_{41,66} + x_{41,67} + x_{41,68} + x_{41,69} + x_{41,70} + x_{41,71} + x_{41,72} + x_{41,73} + x_{41,74} + x_{41,75} + x_{41,76} = 1\\
& x_{42,1} + x_{42,2} + x_{42,3} + x_{42,4} + x_{42,5} + x_{42,6} + x_{42,7} + x_{42,8} + x_{42,9} + x_{42,10} + x_{42,11} + x_{42,12} + x_{42,13} + x_{42,14} + x_{42,15} + x_{42,16} + x_{42,17} + x_{42,18} + x_{42,19} + x_{42,20} + x_{42,21} + x_{42,22} + x_{42,23} + x_{42,24} + x_{42,25} + x_{42,26} + x_{42,27} + x_{42,28} + x_{42,29} + x_{42,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{42,47} + x_{42,48} + x_{42,49} + x_{42,50} + x_{42,51} + x_{42,52} + x_{42,53} + x_{42,54} + x_{42,55} + x_{42,56} + x_{42,57} + x_{42,58} + x_{42,59} + x_{42,60} + x_{42,61} + x_{42,62} + x_{42,63} + x_{42,64} + x_{42,65} + x_{42,66} + x_{42,67} + x_{42,68} + x_{42,69} + x_{42,70} + x_{42,71} + x_{42,72} + x_{42,73} + x_{42,74} + x_{42,75} + x_{42,76} = 1\\
& x_{43,1} + x_{43,2} + x_{43,3} + x_{43,4} + x_{43,5} + x_{43,6} + x_{43,7} + x_{43,8} + x_{43,9} + x_{43,10} + x_{43,11} + x_{43,12} + x_{43,13} + x_{43,14} + x_{43,15} + x_{43,16} + x_{43,17} + x_{43,18} + x_{43,19} + x_{43,20} + x_{43,21} + x_{43,22} + x_{43,23} + x_{43,24} + x_{43,25} + x_{43,26} + x_{43,27} + x_{43,28} + x_{43,29} + x_{43,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{43,47} + x_{43,48} + x_{43,49} + x_{43,50} + x_{43,51} + x_{43,52} + x_{43,53} + x_{43,54} + x_{43,55} + x_{43,56} + x_{43,57} + x_{43,58} + x_{43,59} + x_{43,60} + x_{43,61} + x_{43,62} + x_{43,63} + x_{43,64} + x_{43,65} + x_{43,66} + x_{43,67} + x_{43,68} + x_{43,69} + x_{43,70} + x_{43,71} + x_{43,72} + x_{43,73} + x_{43,74} + x_{43,75} + x_{43,76} = 1\\
& x_{44,1} + x_{44,2} + x_{44,3} + x_{44,4} + x_{44,5} + x_{44,6} + x_{44,7} + x_{44,8} + x_{44,9} + x_{44,10} + x_{44,11} + x_{44,12} + x_{44,13} + x_{44,14} + x_{44,15} + x_{44,16} + x_{44,17} + x_{44,18} + x_{44,19} + x_{44,20} + x_{44,21} + x_{44,22} + x_{44,23} + x_{44,24} + x_{44,25} + x_{44,26} + x_{44,27} + x_{44,28} + x_{44,29} + x_{44,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{44,47} + x_{44,48} + x_{44,49} + x_{44,50} + x_{44,51} + x_{44,52} + x_{44,53} + x_{44,54} + x_{44,55} + x_{44,56} + x_{44,57} + x_{44,58} + x_{44,59} + x_{44,60} + x_{44,61} + x_{44,62} + x_{44,63} + x_{44,64} + x_{44,65} + x_{44,66} + x_{44,67} + x_{44,68} + x_{44,69} + x_{44,70} + x_{44,71} + x_{44,72} + x_{44,73} + x_{44,74} + x_{44,75} + x_{44,76} = 1\\
& x_{45,1} + x_{45,2} + x_{45,3} + x_{45,4} + x_{45,5} + x_{45,6} + x_{45,7} + x_{45,8} + x_{45,9} + x_{45,10} + x_{45,11} + x_{45,12} + x_{45,13} + x_{45,14} + x_{45,15} + x_{45,16} + x_{45,17} + x_{45,18} + x_{45,19} + x_{45,20} + x_{45,21} + x_{45,22} + x_{45,23} + x_{45,24} + x_{45,25} + x_{45,26} + x_{45,27} + x_{45,28} + x_{45,29} + x_{45,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{45,47} + x_{45,48} + x_{45,49} + x_{45,50} + x_{45,51} + x_{45,52} + x_{45,53} + x_{45,54} + x_{45,55} + x_{45,56} + x_{45,57} + x_{45,58} + x_{45,59} + x_{45,60} + x_{45,61} + x_{45,62} + x_{45,63} + x_{45,64} + x_{45,65} + x_{45,66} + x_{45,67} + x_{45,68} + x_{45,69} + x_{45,70} + x_{45,71} + x_{45,72} + x_{45,73} + x_{45,74} + x_{45,75} + x_{45,76} = 1\\
& x_{46,1} + x_{46,2} + x_{46,3} + x_{46,4} + x_{46,5} + x_{46,6} + x_{46,7} + x_{46,8} + x_{46,9} + x_{46,10} + x_{46,11} + x_{46,12} + x_{46,13} + x_{46,14} + x_{46,15} + x_{46,16} + x_{46,17} + x_{46,18} + x_{46,19} + x_{46,20} + x_{46,21} + x_{46,22} + x_{46,23} + x_{46,24} + x_{46,25} + x_{46,26} + x_{46,27} + x_{46,28} + x_{46,29} + x_{46,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{46,47} + x_{46,48} + x_{46,49} + x_{46,50} + x_{46,51} + x_{46,52} + x_{46,53} + x_{46,54} + x_{46,55} + x_{46,56} + x_{46,57} + x_{46,58} + x_{46,59} + x_{46,60} + x_{46,61} + x_{46,62} + x_{46,63} + x_{46,64} + x_{46,65} + x_{46,66} + x_{46,67} + x_{46,68} + x_{46,69} + x_{46,70} + x_{46,71} + x_{46,72} + x_{46,73} + x_{46,74} + x_{46,75} + x_{46,76} = 1\\
& x_{47,1} + x_{47,2} + x_{47,3} + x_{47,4} + x_{47,5} + x_{47,6} + x_{47,7} + x_{47,8} + x_{47,9} + x_{47,10} + x_{47,11} + x_{47,12} + x_{47,13} + x_{47,14} + x_{47,15} + x_{47,16} + x_{47,17} + x_{47,18} + x_{47,19} + x_{47,20} + x_{47,21} + x_{47,22} + x_{47,23} + x_{47,24} + x_{47,25} + x_{47,26} + x_{47,27} + x_{47,28} + x_{47,29} + x_{47,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{47,47} + x_{47,48} + x_{47,49} + x_{47,50} + x_{47,51} + x_{47,52} + x_{47,53} + x_{47,54} + x_{47,55} + x_{47,56} + x_{47,57} + x_{47,58} + x_{47,59} + x_{47,60} + x_{47,61} + x_{47,62} + x_{47,63} + x_{47,64} + x_{47,65} + x_{47,66} + x_{47,67} + x_{47,68} + x_{47,69} + x_{47,70} + x_{47,71} + x_{47,72} + x_{47,73} + x_{47,74} + x_{47,75} + x_{47,76} = 1\\
& x_{48,1} + x_{48,2} + x_{48,3} + x_{48,4} + x_{48,5} + x_{48,6} + x_{48,7} + x_{48,8} + x_{48,9} + x_{48,10} + x_{48,11} + x_{48,12} + x_{48,13} + x_{48,14} + x_{48,15} + x_{48,16} + x_{48,17} + x_{48,18} + x_{48,19} + x_{48,20} + x_{48,21} + x_{48,22} + x_{48,23} + x_{48,24} + x_{48,25} + x_{48,26} + x_{48,27} + x_{48,28} + x_{48,29} + x_{48,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{48,47} + x_{48,48} + x_{48,49} + x_{48,50} + x_{48,51} + x_{48,52} + x_{48,53} + x_{48,54} + x_{48,55} + x_{48,56} + x_{48,57} + x_{48,58} + x_{48,59} + x_{48,60} + x_{48,61} + x_{48,62} + x_{48,63} + x_{48,64} + x_{48,65} + x_{48,66} + x_{48,67} + x_{48,68} + x_{48,69} + x_{48,70} + x_{48,71} + x_{48,72} + x_{48,73} + x_{48,74} + x_{48,75} + x_{48,76} = 1\\
& x_{49,1} + x_{49,2} + x_{49,3} + x_{49,4} + x_{49,5} + x_{49,6} + x_{49,7} + x_{49,8} + x_{49,9} + x_{49,10} + x_{49,11} + x_{49,12} + x_{49,13} + x_{49,14} + x_{49,15} + x_{49,16} + x_{49,17} + x_{49,18} + x_{49,19} + x_{49,20} + x_{49,21} + x_{49,22} + x_{49,23} + x_{49,24} + x_{49,25} + x_{49,26} + x_{49,27} + x_{49,28} + x_{49,29} + x_{49,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{49,47} + x_{49,48} + x_{49,49} + x_{49,50} + x_{49,51} + x_{49,52} + x_{49,53} + x_{49,54} + x_{49,55} + x_{49,56} + x_{49,57} + x_{49,58} + x_{49,59} + x_{49,60} + x_{49,61} + x_{49,62} + x_{49,63} + x_{49,64} + x_{49,65} + x_{49,66} + x_{49,67} + x_{49,68} + x_{49,69} + x_{49,70} + x_{49,71} + x_{49,72} + x_{49,73} + x_{49,74} + x_{49,75} + x_{49,76} = 1\\
& x_{50,1} + x_{50,2} + x_{50,3} + x_{50,4} + x_{50,5} + x_{50,6} + x_{50,7} + x_{50,8} + x_{50,9} + x_{50,10} + x_{50,11} + x_{50,12} + x_{50,13} + x_{50,14} + x_{50,15} + x_{50,16} + x_{50,17} + x_{50,18} + x_{50,19} + x_{50,20} + x_{50,21} + x_{50,22} + x_{50,23} + x_{50,24} + x_{50,25} + x_{50,26} + x_{50,27} + x_{50,28} + x_{50,29} + x_{50,30} + [[\ldots\text{16 terms omitted}\ldots]] + x_{50,47} + x_{50,48} + x_{50,49} + x_{50,50} + x_{50,51} + x_{50,52} + x_{50,53} + x_{50,54} + x_{50,55} + x_{50,56} + x_{50,57} + x_{50,58} + x_{50,59} + x_{50,60} + x_{50,61} + x_{50,62} + x_{50,63} + x_{50,64} + x_{50,65} + x_{50,66} + x_{50,67} + x_{50,68} + x_{50,69} + x_{50,70} + x_{50,71} + x_{50,72} + x_{50,73} + x_{50,74} + x_{50,75} + x_{50,76} = 1\\
& [[\ldots\text{183499 constraints skipped}\ldots]] \\
& y_{27} \in \{0, 1\}\\
& y_{28} \in \{0, 1\}\\
& y_{29} \in \{0, 1\}\\
& y_{30} \in \{0, 1\}\\
& y_{31} \in \{0, 1\}\\
& y_{32} \in \{0, 1\}\\
& y_{33} \in \{0, 1\}\\
& y_{34} \in \{0, 1\}\\
& y_{35} \in \{0, 1\}\\
& y_{36} \in \{0, 1\}\\
& y_{37} \in \{0, 1\}\\
& y_{38} \in \{0, 1\}\\
& y_{39} \in \{0, 1\}\\
& y_{40} \in \{0, 1\}\\
& y_{41} \in \{0, 1\}\\
& y_{42} \in \{0, 1\}\\
& y_{43} \in \{0, 1\}\\
& y_{44} \in \{0, 1\}\\
& y_{45} \in \{0, 1\}\\
& y_{46} \in \{0, 1\}\\
& y_{47} \in \{0, 1\}\\
& y_{48} \in \{0, 1\}\\
& y_{49} \in \{0, 1\}\\
& y_{50} \in \{0, 1\}\\
& y_{51} \in \{0, 1\}\\
& y_{52} \in \{0, 1\}\\
& y_{53} \in \{0, 1\}\\
& y_{54} \in \{0, 1\}\\
& y_{55} \in \{0, 1\}\\
& y_{56} \in \{0, 1\}\\
& y_{57} \in \{0, 1\}\\
& y_{58} \in \{0, 1\}\\
& y_{59} \in \{0, 1\}\\
& y_{60} \in \{0, 1\}\\
& y_{61} \in \{0, 1\}\\
& y_{62} \in \{0, 1\}\\
& y_{63} \in \{0, 1\}\\
& y_{64} \in \{0, 1\}\\
& y_{65} \in \{0, 1\}\\
& y_{66} \in \{0, 1\}\\
& y_{67} \in \{0, 1\}\\
& y_{68} \in \{0, 1\}\\
& y_{69} \in \{0, 1\}\\
& y_{70} \in \{0, 1\}\\
& y_{71} \in \{0, 1\}\\
& y_{72} \in \{0, 1\}\\
& y_{73} \in \{0, 1\}\\
& y_{74} \in \{0, 1\}\\
& y_{75} \in \{0, 1\}\\
& y_{76} \in \{0, 1\}\\
\end{aligned} $$
Dónde f’y es un coste fijo (que hemos puesto de 1) que imponemos por abrir cada sede (código postal) y sum(c .* x)
dónde c es la matriz ajustada de distancias entre los comerciales y las sedes (con el truco de aumentar artificialmente la distancia para los jefes) y x[i,j] es la matriz n x m que indica si la sede i se asigna a comercial j. con .* se hace la multiplicación elemento a elemento , y se suma para obtener el coste total. Al minimizar esto lo que estamos indicando es que asigne sedes a comerciales de forma que se minimice de forma global las distancias a las sedes (queremos que la gente de Almería no le asignes una sede en Huelva). Y además hemos metido las restricciones de que solo un comercial por sede y lo de que los jefes no trabajen demasiado (como mucho 10 sedes por jefe)
Pues ya solo queda dejar que JuMP haga su magia.
Running HiGHS 1.11.0 (git hash: 364c83a51e): Copyright (c) 2025 HiGHS under MIT licence terms
MIP has 92399 rows; 91200 cols; 364496 nonzeros; 91200 integer variables (91200 binary)
Coefficient ranges:
Matrix [1e+00, 1e+00]
Cost [1e+00, 5e+02]
Bound [1e+00, 1e+00]
RHS [1e+00, 1e+02]
Presolving model
92399 rows, 91200 cols, 364496 nonzeros 0s
92399 rows, 91200 cols, 364496 nonzeros 0s
Objective function is integral with scale 1000
Solving MIP model with:
92399 rows
91200 cols (91200 binary, 0 integer, 0 implied int., 0 continuous, 0 domain fixed)
364496 nonzeros
Src: B => Branching; C => Central rounding; F => Feasibility pump; J => Feasibility jump;
H => Heuristic; L => Sub-MIP; P => Empty MIP; R => Randomized rounding; Z => ZI Round;
I => Shifting; S => Solve LP; T => Evaluate node; U => Unbounded; X => User solution;
z => Trivial zero; l => Trivial lower; u => Trivial upper; p => Trivial point
Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work
Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time
J 0 0 0 0.00% -inf 178645.113 Large 0 0 0 0 0.6s
0 0 0 0.00% 21182.055167 178645.113 88.14% 0 0 4 1971 0.9s
C 0 0 0 0.00% 21202.838 95153.418 77.72% 0 0 7 2198 1.0s
L 0 0 0 0.00% 21202.838 21202.838 0.00% 0 0 7 2198 1.4s
1 0 1 100.00% 21202.838 21202.838 0.00% 0 0 7 2228 1.4s
Solving report
Status Optimal
Primal bound 21202.838
Dual bound 21202.838
Gap 0% (tolerance: 0.01%)
P-D integral 0.612597059043
Solution status feasible
21202.838 (objective)
0 (bound viol.)
0 (int. viol.)
0 (row viol.)
Timing 1.44 (total)
0.00 (presolve)
0.00 (solve)
0.00 (postsolve)
Max sub-MIP depth 1
Nodes 1
Repair LPs 0 (0 feasible; 0 iterations)
LP iterations 2228 (total)
0 (strong br.)
227 (separation)
30 (heuristics)
Optimal value: 21202.838
# value.(x) obtiene una matriz con los valores optimizados de las variables x[i,j] (pueden ser algo como 0.999999 o 1.0 por temas de redondeo).
# x_ es una matriz booleana del mismo tamaño que x, indicando qué asignaciones cliente–sede están activas.
# y_ devuelve true o false indicando que sedes se han habierto
x_ = value.(x) .> 1 - 1e-5
y_ = value.(y) .> 1 - 1e-5
#value.(comparacion)
value.(tot_por_indio)
value.(tot_por_jefe)
27-element Vector{Float64}:
1.0
8.0
1.0
10.0
1.0
10.0
9.0
10.0
8.0
1.0
⋮
1.0
10.0
1.0
1.0
1.0
10.0
10.0
9.0
1.0
Pintamos, la verdad es que pintar en Julia no me agrada demasiado
p = Plots.scatter(
cod_postales.centroide_longitud,
cod_postales.centroide_latitud;
markershape = :circle,
markercolor = :blue,
label = nothing,
)
mc = [(y_[j] ? :red : :white) for j in 1:m]
Plots.scatter!(
sedes.centroide_longitud,
sedes.centroide_latitud;
markershape = :square,
markercolor = mc,
markersize = 4,
markerstrokecolor = :red,
markerstrokewidth = 2,
label = nothing,
)
for i in 1:n
for j in 1:m
if x_[i, j] == 1
Plots.plot!(
[cod_postales.centroide_longitud[i], sedes.centroide_longitud[j]],
[cod_postales.centroide_latitud[i], sedes.centroide_latitud[j]];
color = :black,
label = nothing,
)
end
end
end
p
Ahora extraemos las asignaciones matrix x[i,j] y contamos para cada columna j cuantos códigos postales le han caído. Es decir, cuántas le han tocado a cada comercial
1×76 Matrix{Int64}:
1 8 1 10 1 10 9 10 8 1 10 1 … 8 23 55 24 13 28 24 3 10
Lo siguiente es solo comprobar que a cada cod postal solo va un único comercial.
Lo siguiente lo hice hace tiempo y no recuerdo muy bien lo que hace, pero el objetivo era mostrar para cada comercial, cuántos cod postales tiene que visitar. Al final salen tuplas dónde el primer elemento es el índice del comercial y el segndo el total de códigos postales que visita. Como ordenamos poniendo primero a los jefes veremos que como máximo visitan 10 códigos postales y como mínimo 1. Luego vendrán las asignaciones de los pobres indios, dónde alguno puede haber tenido fortuna y solo se le asignan 3 códigos postales. Hace falta un sindicato, claramente
[x for x in 1:10 if x % 2 == 0]
# comprehension lista
asignaciones = Dict()
#= for j in 1:m
asignaciones("clave" => j, "valor" =>
[index for (index, fila)
in enumerate(x_collect[:,j])
if fila .== 1])
end =#
asignaciones = Dict()
for j in 1:m
asignaciones[j] =
[index for (index, fila) in enumerate(x_collect[:,j]) if fila .== 1]
end
for j in 1:m
asignaciones[j] =
cod_postales[ [index for (index, fila) in enumerate(x_collect[:,j]) if fila .== 1], :cod_postal]
end
for j in 1:m
asignaciones[j] =
cod_postales[ [index for (index, fila) in enumerate(x_collect[:,j]) if fila .== 1], [:cod_postal, :provincia]]
end
for j in 1:m
println((j, size(asignaciones[j])[1]))
end
(1, 1)
(2, 8)
(3, 1)
(4, 10)
(5, 1)
(6, 10)
(7, 9)
(8, 10)
(9, 8)
(10, 1)
(11, 10)
(12, 1)
(13, 10)
(14, 1)
(15, 1)
(16, 1)
(17, 9)
(18, 1)
(19, 1)
(20, 10)
(21, 1)
(22, 1)
(23, 1)
(24, 10)
(25, 10)
(26, 9)
(27, 1)
(28, 70)
(29, 14)
(30, 21)
(31, 18)
(32, 4)
(33, 34)
(34, 12)
(35, 15)
(36, 16)
(37, 9)
(38, 49)
(39, 14)
(40, 6)
(41, 12)
(42, 9)
(43, 14)
(44, 24)
(45, 9)
(46, 24)
(47, 33)
(48, 49)
(49, 16)
(50, 11)
(51, 22)
(52, 25)
(53, 8)
(54, 35)
(55, 19)
(56, 11)
(57, 9)
(58, 9)
(59, 22)
(60, 24)
(61, 28)
(62, 21)
(63, 75)
(64, 21)
(65, 31)
(66, 21)
(67, 10)
(68, 8)
(69, 23)
(70, 55)
(71, 24)
(72, 13)
(73, 28)
(74, 24)
(75, 3)
(76, 10)
---
title: IO con Julia
date: '2025-07-20'
categories:
- estadística
- ciencia de datos
- "2025"
description: ''
execute:
message: false
warning: false
echo: true
output: true
format:
html:
toc: true
fig-height: 5
fig-dpi: 300
fig-width: 8
fig-align: center
code-fold: show
code-link: true
code-summary: "Show the code"
code-tools: true
engine: julia
---
::: callout-note
## Listening
<iframe style="border-radius:12px" src="https://open.spotify.com/embed/track/2jGfKzi1RvbkAyffbDyESE?utm_source=generator" width="100%" height="352" frameBorder="0" allowfullscreen="" allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy">
</iframe>
:::
Este post viene a ampliar el de la IO al servicio del mal. y está en Work in Progress.
```{julia}
using Pkg
Pkg.activate(@__DIR__)
Pkg.instantiate()
using JuMP, DataFrames, CSV, Plots, HiGHS
```
```{julia}
ANDALUCIA = ["ALMERIA", "CADIZ",
"CORDOBA","GRANADA",
"HUELVA", "JAEN",
"MALAGA",
"SEVILLA"]
cod_postales_raw = DataFrame(CSV.File("cod_postales.csv"))
sedes_raw = DataFrame(CSV.File("sedes.csv"))
cod_postales_raw
```
Seleccionamos solo Andalucía. Tanto para las sedes como para las códigos postales
```{julia}
cod_postales = cod_postales_raw[[i ∈ ANDALUCIA for i in cod_postales_raw.provincia ], :]
sedes = subset(sedes_raw, :provincia => ByRow(x -> x ∈ ANDALUCIA))
```
Ordenamos el dataset de sedes por si son jefes o indios
```{julia}
sort!(sedes, :tipo, rev = true)
```
Creamos funcion haversine que nos va a dar la distancia entre los puntos dada longitud y latitud. Hay que pasarle las longitudes y latitude y el radio estimado de la tierra.
```{julia}
"""
haversine(lat1, long1, lat2, long2, r = 6372.8)
Compute the haversine distance between two points on a sphere of radius `r`,
where the points are given by the latitude/longitude pairs `lat1/long1` and
`lat2/long2` (in degrees).
"""
function haversine(lat1, long1, lat2, long2, r = 6372.8)
lat1, long1 = deg2rad(lat1), deg2rad(long1)
lat2, long2 = deg2rad(lat2), deg2rad(long2)
hav(a, b) = sin((b - a) / 2)^2
inner_term = hav(lat1, lat2) + cos(lat1) * cos(lat2) * hav(long1, long2)
d = 2 * r * asin(sqrt(inner_term))
# Round distance to nearest kilometer.
return round( d, digits = 2)
end
```
y ahora calculamos las distancias entre todos los códigos postales y todas las sedes de los trabajadores.
En Julia esto es muy rápido
```{julia}
# number of clients
n = size(cod_postales,1)
# number of comerciales (facilities)
m = size(sedes, 1)
# esto es como en python, una list comprehension
c = [haversine(
cod_postales.centroide_latitud[i], cod_postales.centroide_longitud[i],
sedes.centroide_latitud[j], sedes.centroide_longitud[j])
for i in 1:n, j in 1:m]
```
Ahora para hacer truco de que a los jefes les toque códigos postales más cercanos a su sede lo que hacemos es aumentar la distancia artificialmente.
```{julia}
# utilizamos operador ternario
# Si eres jefe te pongo distancia 1.1, si no 0.9
for j in 1:m
c[:,j] = sedes.tipo[j] == "jefe" ? 1.1 * c[:, j] : 0.9 * c[:,j]
end
```
Contamos cuantos jefes y cuantos indios hay.
```{julia}
n_jefes = sum(sedes.tipo .=="jefe")
print(n_jefes)
```
```{julia}
n_indios = m - n_jefes
print(n_indios)
```
Y ahora definimos el problema de optimización y sus restricciones
```{julia}
# Fixed costs
f = ones(m);
```
Definimos el modelo dónde x va a ser una matriz de variables binarias qeu va a indicar si un código postal (de 1 a n) se asigna a un comercial (jefe o indio) va de 1 a m. Y la variable y va a indicar si ese código postal (o tienda) está asignado o no. Si no está asignado entonces se podrá asignar a un comercial.
```{julia}
ufl = Model(HiGHS.Optimizer)
@variable(ufl, x[1:n, 1:m], Bin);
@variable(ufl, y[1:m], Bin);
```
Ahora vamos a poner restricione está asignado o no. Si no está asignado entonces se podrá asignar a un comercial.
```{julia}
ufl = Model(HiGHS.Optimizer)
@variable(ufl, x[1:n, 1:m], Bin);
@variable(ufl, y[1:m], Bin);
```
Ahora vamos a poner restriciones
Lo primero es definir una serie de restricciones de forma que a cada código postal sólo se le puede asignar un comercial. Eso se define haciendo que en la matriz X , que tiene n filas (sedes) y j columnas (comercials) , al sumar por fila el valor sea igual a 1. Es decir, a cada código postal sólo puede ir un comercial. (Se podría cambiar a que fueran 2 por ejemplo)
```{julia}
# esta restriccion es poner que a cada cod postal solo puede ir un comecial, (sea indio o jefe)
@constraint(ufl, client_service[i in 1:n], sum(x[i, j] for j in 1:m) == 1);
```
La siguiente restricción es poner que un comercial sólo puede ser asignado a un código postal (sede, tienda) que esté abierta.
Esto se hace haciendo que la matriz x[i,j] sea menor o igual que y[j]. puesto que y[j] vale 1 si la "tienda" está abierta, y por tanto si está cerrada vale 0 y x[i,j] por narices tiene que ser 0 , es decir, si la "tienda" ha sido asignada ya no se puede
```{julia}
# siguiente restricción es poner que un cod postales solo puede ir a una que esté abierta
# esto es, si y[j] = 0 significa sede cerrada y no se puede asignar nadie ahí
@constraint(ufl, open_facility[i in 1:n, j in 1:m], x[i, j] <= y[j]);
```
Estas dos restricciones implican.
- Cada código postal sólo puede ser visitado por un único comercial
- Un comercial sólo puede ser asignado a una sede si esta está abierta
Si tengo 3 cod postales y 2 comerciales
```
sum(x[1,1], x[1,2]) == 1 # cod postal 1 → un solo comercial
sum(x[2,1], x[2,2]) == 1 # cod postal 2 → un solo comercial
sum(x[3,1], x[3,2]) == 1 # cod postal 3 → un solo comercial
x[i,j] <= y[j] # Solo puedes usar comercial j si está abierto
```
De esta forma, un comercial puede ir a varios códigos postales pero un código postal solo puede ser visitado por un comercial.
Ahora vamos con las restriciones diferenciadas según el tipo de comercial.
La restricción para los indios es que al menos tienen que visitar 3 códigos postales cada uno y como máximo 100. Mientras que para los jefes se impone que al menos tienen que visitar un código postal (si no, sería muy cantoso) y cómo máximo 10.
```{julia}
# restricciones para los indios, jefes
@constraint(ufl, tot_por_indio[j in (n_jefes+1):m], 3 <= sum(x[i, j] for i in 1:n) <= 100);
@constraint(ufl, tot_por_jefe[j ∈ 1:n_jefes], 1<=sum(x[i, j] for i in 1:n) <= 10);
```
Si hacemos print(ufl) veremos las restricciones planteadas, pero son muchas.
Y con esto ya podemos plantear el objetivo. que va a ser
```{julia}
@objective(ufl, Min, f'y + sum(c .* x));
```
En Jump también podemos escribir la formulación en LaTex
```{julia}
latex_formulation(ufl)
```
Dónde f'y es un coste fijo (que hemos puesto de 1) que imponemos por abrir cada sede (código postal)
y
sum(c .* x)
dónde c es la matriz ajustada de distancias entre los comerciales y las sedes (con el truco de aumentar artificialmente la distancia para los jefes) y x[i,j] es la matriz n x m que indica si la sede i se asigna a comercial j. con .* se hace la multiplicación elemento a elemento , y se suma para obtener el coste total.
Al minimizar esto lo que estamos indicando es que asigne sedes a comerciales de forma que se minimice de forma global las distancias a las sedes (queremos que la gente de Almería no le asignes una sede en Huelva). Y además hemos metido las restricciones de que solo un comercial por sede y lo de que los jefes no trabajen demasiado (como mucho 10 sedes por jefe)
Pues ya solo queda dejar que JuMP haga su magia.
```{julia}
optimize!(ufl)
println("Optimal value: ", objective_value(ufl))
```
```{julia}
# value.(x) obtiene una matriz con los valores optimizados de las variables x[i,j] (pueden ser algo como 0.999999 o 1.0 por temas de redondeo).
# x_ es una matriz booleana del mismo tamaño que x, indicando qué asignaciones cliente–sede están activas.
# y_ devuelve true o false indicando que sedes se han habierto
x_ = value.(x) .> 1 - 1e-5
y_ = value.(y) .> 1 - 1e-5
#value.(comparacion)
value.(tot_por_indio)
value.(tot_por_jefe)
```
Pintamos, la verdad es que pintar en Julia no me agrada demasiado
```{julia}
p = Plots.scatter(
cod_postales.centroide_longitud,
cod_postales.centroide_latitud;
markershape = :circle,
markercolor = :blue,
label = nothing,
)
mc = [(y_[j] ? :red : :white) for j in 1:m]
Plots.scatter!(
sedes.centroide_longitud,
sedes.centroide_latitud;
markershape = :square,
markercolor = mc,
markersize = 4,
markerstrokecolor = :red,
markerstrokewidth = 2,
label = nothing,
)
for i in 1:n
for j in 1:m
if x_[i, j] == 1
Plots.plot!(
[cod_postales.centroide_longitud[i], sedes.centroide_longitud[j]],
[cod_postales.centroide_latitud[i], sedes.centroide_latitud[j]];
color = :black,
label = nothing,
)
end
end
end
p
```
Ahora extraemos las asignaciones matrix x[i,j] y contamos para cada columna j cuantos códigos postales le han caído. Es decir, cuántas le han tocado a cada comercial
```{julia}
#
x_collect= collect(x_)
#sum(collect(x_), dims=1)
sum(x_, dims = 1)
```
Lo siguiente es solo comprobar que a cada cod postal solo va un único comercial.
```{julia}
sum(x_, dims = 2)
```
Lo siguiente lo hice hace tiempo y no recuerdo muy bien lo que hace, pero el objetivo era mostrar para cada comercial, cuántos cod postales tiene que visitar. Al final salen tuplas dónde el primer elemento es el índice del comercial y el segndo el total de códigos postales que visita. Como ordenamos poniendo primero a los jefes veremos que como máximo visitan 10 códigos postales y como mínimo 1. Luego vendrán las asignaciones de los pobres indios, dónde alguno puede haber tenido fortuna y solo se le asignan 3 códigos postales. Hace falta un sindicato, claramente
```{julia}
[x for x in 1:10 if x % 2 == 0]
# comprehension lista
asignaciones = Dict()
#= for j in 1:m
asignaciones("clave" => j, "valor" =>
[index for (index, fila)
in enumerate(x_collect[:,j])
if fila .== 1])
end =#
asignaciones = Dict()
for j in 1:m
asignaciones[j] =
[index for (index, fila) in enumerate(x_collect[:,j]) if fila .== 1]
end
for j in 1:m
asignaciones[j] =
cod_postales[ [index for (index, fila) in enumerate(x_collect[:,j]) if fila .== 1], :cod_postal]
end
for j in 1:m
asignaciones[j] =
cod_postales[ [index for (index, fila) in enumerate(x_collect[:,j]) if fila .== 1], [:cod_postal, :provincia]]
end
for j in 1:m
println((j, size(asignaciones[j])[1]))
end
```