IGJSP 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
IGJSP/generador.py
CHANGED
|
@@ -3,16 +3,18 @@ import datetime
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
import pickle
|
|
6
|
+
import re
|
|
6
7
|
from itertools import combinations
|
|
8
|
+
|
|
7
9
|
import networkx as nx
|
|
8
10
|
import numpy as np
|
|
9
|
-
import re
|
|
10
11
|
|
|
11
12
|
np.set_printoptions(linewidth=np.inf, threshold=np.inf, formatter={"int": lambda x: f"{x}"})
|
|
12
13
|
|
|
13
|
-
from scipy.stats import expon, norm, uniform
|
|
14
14
|
from pprint import pprint
|
|
15
15
|
|
|
16
|
+
from scipy.stats import expon, norm, uniform
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
def f(x):
|
|
18
20
|
return int(np.exp(-int(x)/100)*100)
|
|
@@ -23,6 +25,13 @@ def g(x):
|
|
|
23
25
|
def t(c):
|
|
24
26
|
return 4.0704 * np.log(2) / np.log(1 + (c* 2.5093)**3)
|
|
25
27
|
|
|
28
|
+
|
|
29
|
+
#################################################################################
|
|
30
|
+
# #
|
|
31
|
+
# JSP #
|
|
32
|
+
# #
|
|
33
|
+
#################################################################################
|
|
34
|
+
|
|
26
35
|
class JSP:
|
|
27
36
|
def __init__(self, jobs, machines, ProcessingTime=np.array([]), EnergyConsumption=np.array([]), ReleaseDateDueDate=np.array([]), Orden=np.array([])) -> None:
|
|
28
37
|
self.numJobs = jobs
|
|
@@ -115,10 +124,325 @@ class JSP:
|
|
|
115
124
|
else:
|
|
116
125
|
return expon(loc=duration, scale=duration/2).rvs()
|
|
117
126
|
|
|
118
|
-
def
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
def loadPythonFile(path):
|
|
128
|
+
"""
|
|
129
|
+
Carga un fichero .pkl generado por savePythonFile y devuelve un JSP.
|
|
130
|
+
"""
|
|
131
|
+
with open(path, 'rb') as f:
|
|
132
|
+
obj = pickle.load(f)
|
|
133
|
+
|
|
134
|
+
# Si ya es un JSP, lo devolvemos tal cual
|
|
135
|
+
if isinstance(obj, JSP):
|
|
136
|
+
return obj
|
|
137
|
+
|
|
138
|
+
# Si es un dict con la misma estructura que usamos en loadJsonFile, construimos el JSP
|
|
139
|
+
if isinstance(obj, dict) and all(
|
|
140
|
+
k in obj for k in ['jobs', 'machines', 'ProcessingTime', 'EnergyConsumption', 'ReleaseDateDueDate', 'Orden']
|
|
141
|
+
):
|
|
142
|
+
return JSP(**obj)
|
|
143
|
+
|
|
144
|
+
raise TypeError(
|
|
145
|
+
f"El objeto cargado desde {path} no es un JSP ni un diccionario compatible para construir uno."
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
def loadDznFile(path):
|
|
149
|
+
"""
|
|
150
|
+
Carga un .dzn generado por saveDznFile y devuelve un JSP.
|
|
151
|
+
Soporta rddd = 0, 1, 2 (sin fechas, fechas por job, fechas por operación).
|
|
152
|
+
"""
|
|
153
|
+
with open(path, 'r', encoding='utf-8') as f:
|
|
154
|
+
text = f.read()
|
|
155
|
+
|
|
156
|
+
numJobs = _parse_int_var(text, 'jobs')
|
|
157
|
+
numMchs = _parse_int_var(text, 'machines')
|
|
158
|
+
speed = _parse_int_var(text, 'Speed', default=1)
|
|
159
|
+
|
|
160
|
+
time_flat = _parse_array_var(text, 'time')
|
|
161
|
+
energy_flat = _parse_array_var(text, 'energy')
|
|
162
|
+
prec_flat = _parse_array_var(text, 'precedence')
|
|
163
|
+
|
|
164
|
+
if time_flat is None or energy_flat is None or prec_flat is None:
|
|
165
|
+
raise ValueError("Faltan variables obligatorias (time, energy o precedence) en el fichero DZN.")
|
|
166
|
+
|
|
167
|
+
# Comprobar tamaños
|
|
168
|
+
expected_te = numJobs * numMchs * speed
|
|
169
|
+
if time_flat.size != expected_te or energy_flat.size != expected_te:
|
|
170
|
+
raise ValueError(
|
|
171
|
+
f"Tamaños incompatibles en time/energy: esperado {expected_te}, "
|
|
172
|
+
f"time={time_flat.size}, energy={energy_flat.size}"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
expected_prec = numJobs * numMchs
|
|
176
|
+
if prec_flat.size != expected_prec:
|
|
177
|
+
raise ValueError(
|
|
178
|
+
f"Tamaño incompatible en precedence: esperado {expected_prec}, precedence={prec_flat.size}"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
ProcessingTime = time_flat.reshape((numJobs, numMchs, speed))
|
|
182
|
+
EnergyConsumption = energy_flat.reshape((numJobs, numMchs, speed))
|
|
183
|
+
precedence = prec_flat.reshape((numJobs, numMchs))
|
|
184
|
+
|
|
185
|
+
# Reconstruir Orden a partir de la precedencia (cada fila es posiciones 0..numMchs-1 por máquina)
|
|
186
|
+
Orden = np.zeros((numJobs, numMchs), dtype=int)
|
|
187
|
+
for j in range(numJobs):
|
|
188
|
+
# precedence[j, m] = posición de la máquina m en la secuencia
|
|
189
|
+
# argsort da el índice de la máquina por orden de prioridad
|
|
190
|
+
Orden[j, :] = np.argsort(precedence[j, :])
|
|
191
|
+
|
|
192
|
+
# Release / Due dates (pueden no existir)
|
|
193
|
+
release_flat = _parse_array_var(text, 'releaseDate')
|
|
194
|
+
due_flat = _parse_array_var(text, 'dueDate')
|
|
195
|
+
|
|
196
|
+
if release_flat is None or due_flat is None:
|
|
197
|
+
# rddd = 0
|
|
198
|
+
ReleaseDueDate = np.array([])
|
|
199
|
+
else:
|
|
200
|
+
# O bien vector por job, o matriz jobs x machines
|
|
201
|
+
if release_flat.size == numJobs and due_flat.size == numJobs:
|
|
202
|
+
# rddd = 1 → (numJobs, 2)
|
|
203
|
+
ReleaseDueDate = np.zeros((numJobs, 2), dtype=int)
|
|
204
|
+
ReleaseDueDate[:, 0] = release_flat
|
|
205
|
+
ReleaseDueDate[:, 1] = due_flat
|
|
206
|
+
elif release_flat.size == numJobs * numMchs and due_flat.size == numJobs * numMchs:
|
|
207
|
+
# rddd = 2 → (numJobs, numMchs, 2)
|
|
208
|
+
ReleaseDueDate = np.zeros((numJobs, numMchs, 2), dtype=int)
|
|
209
|
+
ReleaseDueDate[:, :, 0] = release_flat.reshape((numJobs, numMchs))
|
|
210
|
+
ReleaseDueDate[:, :, 1] = due_flat.reshape((numJobs, numMchs))
|
|
211
|
+
else:
|
|
212
|
+
raise ValueError(
|
|
213
|
+
"Los tamaños de releaseDate/dueDate no cuadran ni con rddd=1 ni con rddd=2."
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
sol = {
|
|
217
|
+
'jobs': numJobs,
|
|
218
|
+
'machines': numMchs,
|
|
219
|
+
'ProcessingTime': ProcessingTime,
|
|
220
|
+
'EnergyConsumption': EnergyConsumption,
|
|
221
|
+
'ReleaseDateDueDate': ReleaseDueDate,
|
|
222
|
+
'Orden': Orden
|
|
223
|
+
}
|
|
224
|
+
return JSP(**sol)
|
|
225
|
+
|
|
226
|
+
def loadTaillardFile(path):
|
|
227
|
+
"""
|
|
228
|
+
Carga un fichero de texto generado por saveTaillardStandardFile y devuelve un JSP.
|
|
229
|
+
Formato esperado:
|
|
230
|
+
|
|
231
|
+
Number of jobs: J
|
|
232
|
+
Number of machines: M
|
|
233
|
+
|
|
234
|
+
Processing times:
|
|
235
|
+
... J filas, cada una con M enteros ...
|
|
236
|
+
|
|
237
|
+
Energy consumption:
|
|
238
|
+
... J filas, cada una con M enteros ...
|
|
239
|
+
|
|
240
|
+
Machine order:
|
|
241
|
+
... J filas, cada una con M enteros ...
|
|
242
|
+
"""
|
|
243
|
+
with open(path, 'r') as f:
|
|
244
|
+
lines = [line.strip() for line in f]
|
|
245
|
+
|
|
246
|
+
# Leer encabezado
|
|
247
|
+
# Number of jobs: X
|
|
248
|
+
# Number of machines: Y
|
|
249
|
+
numJobs = None
|
|
250
|
+
numMchs = None
|
|
251
|
+
|
|
252
|
+
i = 0
|
|
253
|
+
while i < len(lines):
|
|
254
|
+
line = lines[i]
|
|
255
|
+
if line.startswith("Number of jobs"):
|
|
256
|
+
numJobs = int(line.split(":")[1].strip())
|
|
257
|
+
elif line.startswith("Number of machines"):
|
|
258
|
+
numMchs = int(line.split(":")[1].strip())
|
|
259
|
+
if numJobs is not None and numMchs is not None:
|
|
260
|
+
i += 1
|
|
261
|
+
break
|
|
262
|
+
i += 1
|
|
263
|
+
|
|
264
|
+
if numJobs is None or numMchs is None:
|
|
265
|
+
raise ValueError("No se pudieron leer numJobs / numMchs del fichero Taillard.")
|
|
266
|
+
|
|
267
|
+
# Saltar líneas vacías hasta "Processing times:"
|
|
268
|
+
while i < len(lines) and lines[i] == "":
|
|
269
|
+
i += 1
|
|
270
|
+
if i >= len(lines) or not lines[i].startswith("Processing times"):
|
|
271
|
+
raise ValueError("No se encontró la sección 'Processing times:' en el fichero Taillard.")
|
|
272
|
+
i += 1 # pasar la línea de cabecera
|
|
273
|
+
|
|
274
|
+
# Leer matriz de tiempos de procesamiento (J filas)
|
|
275
|
+
proc_by_order = np.zeros((numJobs, numMchs), dtype=int)
|
|
276
|
+
for j in range(numJobs):
|
|
277
|
+
while i < len(lines) and lines[i] == "":
|
|
278
|
+
i += 1
|
|
279
|
+
parts = lines[i].split()
|
|
280
|
+
if len(parts) != numMchs:
|
|
281
|
+
raise ValueError(
|
|
282
|
+
f"Línea de tiempos de procesamiento para job {j} tiene {len(parts)} elementos, "
|
|
283
|
+
f"pero se esperaban {numMchs}."
|
|
284
|
+
)
|
|
285
|
+
proc_by_order[j, :] = [int(x) for x in parts]
|
|
286
|
+
i += 1
|
|
287
|
+
|
|
288
|
+
# Saltar hasta "Energy consumption:"
|
|
289
|
+
while i < len(lines) and lines[i] == "":
|
|
290
|
+
i += 1
|
|
291
|
+
if i >= len(lines) or not lines[i].startswith("Energy consumption"):
|
|
292
|
+
raise ValueError("No se encontró la sección 'Energy consumption:' en el fichero Taillard.")
|
|
293
|
+
i += 1 # cabecera
|
|
294
|
+
|
|
295
|
+
energy_by_order = np.zeros((numJobs, numMchs), dtype=int)
|
|
296
|
+
for j in range(numJobs):
|
|
297
|
+
while i < len(lines) and lines[i] == "":
|
|
298
|
+
i += 1
|
|
299
|
+
parts = lines[i].split()
|
|
300
|
+
if len(parts) != numMchs:
|
|
301
|
+
raise ValueError(
|
|
302
|
+
f"Línea de consumo de energía para job {j} tiene {len(parts)} elementos, "
|
|
303
|
+
f"pero se esperaban {numMchs}."
|
|
304
|
+
)
|
|
305
|
+
energy_by_order[j, :] = [int(x) for x in parts]
|
|
306
|
+
i += 1
|
|
307
|
+
|
|
308
|
+
# Saltar hasta "Machine order:"
|
|
309
|
+
while i < len(lines) and lines[i] == "":
|
|
310
|
+
i += 1
|
|
311
|
+
if i >= len(lines) or not lines[i].startswith("Machine order"):
|
|
312
|
+
raise ValueError("No se encontró la sección 'Machine order:' en el fichero Taillard.")
|
|
313
|
+
i += 1 # cabecera
|
|
314
|
+
|
|
315
|
+
Orden = np.zeros((numJobs, numMchs), dtype=int)
|
|
316
|
+
for j in range(numJobs):
|
|
317
|
+
while i < len(lines) and lines[i] == "":
|
|
318
|
+
i += 1
|
|
319
|
+
parts = lines[i].split()
|
|
320
|
+
if len(parts) != numMchs:
|
|
321
|
+
raise ValueError(
|
|
322
|
+
f"Línea de orden de máquinas para job {j} tiene {len(parts)} elementos, "
|
|
323
|
+
f"pero se esperaban {numMchs}."
|
|
324
|
+
)
|
|
325
|
+
Orden[j, :] = [int(x) for x in parts]
|
|
326
|
+
i += 1
|
|
327
|
+
|
|
328
|
+
# Reconstruir ProcessingTime y EnergyConsumption con speed=1
|
|
329
|
+
speed = 1
|
|
330
|
+
ProcessingTime = np.zeros((numJobs, numMchs, speed), dtype=int)
|
|
331
|
+
EnergyConsumption = np.zeros((numJobs, numMchs, speed), dtype=int)
|
|
332
|
+
|
|
333
|
+
for j in range(numJobs):
|
|
334
|
+
for pos in range(numMchs):
|
|
335
|
+
machine = Orden[j, pos]
|
|
336
|
+
ProcessingTime[j, machine, 0] = proc_by_order[j, pos]
|
|
337
|
+
EnergyConsumption[j, machine, 0] = energy_by_order[j, pos]
|
|
338
|
+
|
|
339
|
+
# Taillard estándar: sin release/due dates → rddd=0
|
|
340
|
+
ReleaseDueDate = np.array([])
|
|
341
|
+
|
|
342
|
+
sol = {
|
|
343
|
+
'jobs': numJobs,
|
|
344
|
+
'machines': numMchs,
|
|
345
|
+
'ProcessingTime': ProcessingTime,
|
|
346
|
+
'EnergyConsumption': EnergyConsumption,
|
|
347
|
+
'ReleaseDateDueDate': ReleaseDueDate,
|
|
348
|
+
'Orden': Orden
|
|
349
|
+
}
|
|
350
|
+
return JSP(**sol)
|
|
351
|
+
|
|
352
|
+
def loadJsonFile(path):
|
|
353
|
+
with open(path, "r") as f:
|
|
354
|
+
data = json.load(f)
|
|
355
|
+
numJobs = len(data["nbJobs"])
|
|
356
|
+
numMchs = len(data["nbMchs"])
|
|
357
|
+
speed = data["speed"]
|
|
358
|
+
|
|
359
|
+
# # Load KPIs (opcional)
|
|
360
|
+
# min_makespan = data.get("minMakespan", None)
|
|
361
|
+
# min_energy = data.get("minEnergy", None)
|
|
362
|
+
# max_min_makespan = data.get("maxMinMakespan", None)
|
|
363
|
+
# max_min_energy = data.get("maxMinEnergy", None)
|
|
364
|
+
|
|
365
|
+
# Prepare empty structures
|
|
366
|
+
ProcessingTime = np.zeros((numJobs, numMchs, speed), dtype=int)
|
|
367
|
+
EnergyConsumption = np.zeros((numJobs, numMchs, speed), dtype=int)
|
|
368
|
+
Orden_list = [[] for _ in range(numJobs)]
|
|
369
|
+
|
|
370
|
+
# Detect rddd mode
|
|
371
|
+
# rddd = 0 → no release/due dates
|
|
372
|
+
# rddd = 1 → job-level RDF
|
|
373
|
+
# rddd = 2 → operation-level RDF
|
|
374
|
+
rddd = 0
|
|
375
|
+
if data["timeEnergy"]:
|
|
376
|
+
if "release-date" in data["timeEnergy"][0]:
|
|
377
|
+
rddd = 1
|
|
378
|
+
for m in data["timeEnergy"][0]["operations"]:
|
|
379
|
+
if "release-date" in data["timeEnergy"][0]["operations"][m]:
|
|
380
|
+
rddd = 2
|
|
381
|
+
break
|
|
382
|
+
|
|
383
|
+
# Initialize ReleaseDueDate array according to rddd
|
|
384
|
+
if rddd == 1:
|
|
385
|
+
ReleaseDueDate = np.zeros((numJobs, 2), dtype=int)
|
|
386
|
+
elif rddd == 2:
|
|
387
|
+
ReleaseDueDate = np.zeros((numJobs, numMchs, 2), dtype=int)
|
|
388
|
+
else:
|
|
389
|
+
# No dates: devolver array vacío para que __init__ detecte rddd=0
|
|
390
|
+
ReleaseDueDate = np.array([])
|
|
391
|
+
|
|
392
|
+
# -------------------------
|
|
393
|
+
# Load jobs & operations
|
|
394
|
+
# -------------------------
|
|
395
|
+
for job_data in data["timeEnergy"]:
|
|
396
|
+
job = int(job_data["jobId"])
|
|
397
|
+
|
|
398
|
+
# Optional job-level release/due dates
|
|
399
|
+
if rddd == 1:
|
|
400
|
+
ReleaseDueDate[job, 0] = int(job_data["release-date"])
|
|
401
|
+
ReleaseDueDate[job, 1] = int(job_data["due-date"])
|
|
402
|
+
|
|
403
|
+
for machine_str, op_data in job_data["operations"].items():
|
|
404
|
+
machine = int(machine_str)
|
|
405
|
+
Orden_list[job].append(machine)
|
|
406
|
+
|
|
407
|
+
# Load speed-scaling arrays
|
|
408
|
+
proc_times = [int(entry["procTime"]) for entry in op_data["speed-scaling"]]
|
|
409
|
+
energies = [int(entry["energyCons"]) for entry in op_data["speed-scaling"]]
|
|
410
|
+
|
|
411
|
+
# Aseguramos longitud speed
|
|
412
|
+
# Si speed > len(proc_times) -> rellenamos con ceros (o ajustar según tu política)
|
|
413
|
+
proc_arr = np.zeros((speed,), dtype=int)
|
|
414
|
+
en_arr = np.zeros((speed,), dtype=int)
|
|
415
|
+
L = min(len(proc_times), speed)
|
|
416
|
+
proc_arr[:L] = proc_times[:L]
|
|
417
|
+
en_arr[:L] = energies[:L]
|
|
418
|
+
|
|
419
|
+
ProcessingTime[job, machine, :] = proc_arr
|
|
420
|
+
EnergyConsumption[job, machine, :] = en_arr
|
|
421
|
+
|
|
422
|
+
if rddd == 2:
|
|
423
|
+
ReleaseDueDate[job, machine, 0] = int(op_data["release-date"])
|
|
424
|
+
ReleaseDueDate[job, machine, 1] = int(op_data["due-date"])
|
|
425
|
+
|
|
426
|
+
# Convertir Orden a ndarray (shape = numJobs x numMchs)
|
|
427
|
+
Orden = np.zeros((numJobs, numMchs), dtype=int)
|
|
428
|
+
for j in range(numJobs):
|
|
429
|
+
if len(Orden_list[j]) != numMchs:
|
|
430
|
+
# Si por algun motivo no tiene todas las máquinas,
|
|
431
|
+
# rellenamos con -1 o lanzamos error; aquí uso -1.
|
|
432
|
+
row = Orden_list[j] + [-1] * (numMchs - len(Orden_list[j]))
|
|
433
|
+
else:
|
|
434
|
+
row = Orden_list[j]
|
|
435
|
+
Orden[j, :] = np.array(row, dtype=int)
|
|
436
|
+
|
|
437
|
+
sol = {
|
|
438
|
+
'jobs': numJobs,
|
|
439
|
+
'machines': numMchs,
|
|
440
|
+
'ProcessingTime': ProcessingTime,
|
|
441
|
+
'EnergyConsumption': EnergyConsumption,
|
|
442
|
+
'ReleaseDateDueDate': ReleaseDueDate, # <-- ahora es array, no int
|
|
443
|
+
'Orden': Orden
|
|
444
|
+
}
|
|
445
|
+
return JSP(**sol)
|
|
122
446
|
|
|
123
447
|
def saveJsonFile(self, path):
|
|
124
448
|
self.JSP = {
|
|
@@ -141,13 +465,13 @@ class JSP:
|
|
|
141
465
|
for machine in self.Orden[job]:
|
|
142
466
|
machine = int(machine)
|
|
143
467
|
new["operations"][machine] = {"speed-scaling" :
|
|
144
|
-
|
|
468
|
+
[
|
|
145
469
|
{"procTime" : int(proc),
|
|
146
|
-
|
|
470
|
+
"energyCons" : int(energy)
|
|
147
471
|
}
|
|
148
472
|
for proc, energy in zip(self.ProcessingTime[job, machine],self.EnergyConsumption[job, machine])
|
|
149
|
-
|
|
150
|
-
|
|
473
|
+
]
|
|
474
|
+
}
|
|
151
475
|
if self.rddd == 2:
|
|
152
476
|
new["operations"][machine]["release-date"] = int(self.ReleaseDueDate[job][machine][0])
|
|
153
477
|
new["operations"][machine]["due-date"] = int(self.ReleaseDueDate[job][machine][1])
|
|
@@ -183,6 +507,11 @@ class JSP:
|
|
|
183
507
|
|
|
184
508
|
f.write(json_str)
|
|
185
509
|
|
|
510
|
+
def savePythonFile(self, path):
|
|
511
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
512
|
+
with open(path, 'wb') as f:
|
|
513
|
+
pickle.dump(self, f)
|
|
514
|
+
|
|
186
515
|
def saveDznFile(self, InputDir, OutputDir):
|
|
187
516
|
indexProblema = OutputDir.split("/")[-2]
|
|
188
517
|
OutputDir = "/".join(OutputDir.split("/")[:-2])
|
|
@@ -202,35 +531,30 @@ class JSP:
|
|
|
202
531
|
"machines": data.numMchs,
|
|
203
532
|
"jobs": data.numJobs,
|
|
204
533
|
"Speed": s,
|
|
205
|
-
"time": time.flatten(),
|
|
206
|
-
"energy": energy.flatten(),
|
|
534
|
+
"time": str(time.flatten()).replace(" ", ", "),
|
|
535
|
+
"energy": str(energy.flatten()).replace(" ", ", ")
|
|
207
536
|
}
|
|
208
537
|
|
|
209
538
|
if t == 1:
|
|
210
539
|
replace_data["releaseDate"] = str([int(data.ReleaseDueDate[job, 0]) for job in range(data.numJobs)]).replace(", ", " ")
|
|
211
540
|
replace_data["dueDate"] = str([int(data.ReleaseDueDate[job, 1]) for job in range(data.numJobs)]).replace(", ", " ")
|
|
212
541
|
elif t == 2:
|
|
213
|
-
replace_data["releaseDate"] = data.ReleaseDueDate[:, :, 0].flatten()
|
|
214
|
-
replace_data["dueDate"] = data.ReleaseDueDate[:, :, 1].flatten()
|
|
542
|
+
replace_data["releaseDate"] = str(data.ReleaseDueDate[:, :, 0].flatten()).replace(", ", " ")
|
|
543
|
+
replace_data["dueDate"] = str(data.ReleaseDueDate[:, :, 1].flatten()).replace(", ", " ")
|
|
215
544
|
|
|
216
545
|
for job in range(data.numJobs):
|
|
217
546
|
for i, prioridad in enumerate(range(data.numMchs)):
|
|
218
547
|
precedence[job, data.Orden[job, prioridad]] = i
|
|
219
548
|
|
|
220
|
-
replace_data["precedence"] = precedence.flatten()
|
|
549
|
+
replace_data["precedence"] = str(precedence.flatten()).replace(" ", ",")
|
|
221
550
|
|
|
222
551
|
with open(f"./Minizinc/Types/RD/JSP/type{t}.dzn", "r", encoding="utf-8") as file:
|
|
223
552
|
filedata = file.read()
|
|
224
553
|
for k, v in replace_data.items():
|
|
225
554
|
filedata = filedata.replace("{" + k + "}", str(v))
|
|
226
|
-
|
|
227
555
|
os.makedirs(f"{OutputDir}/", exist_ok=True)
|
|
228
|
-
|
|
229
556
|
with open(f"{OutputDir}/{indexProblema}-{t}-{s}.dzn", "w+", encoding="utf-8") as new:
|
|
230
557
|
new.write(filedata)
|
|
231
|
-
# print(f"{OutputDir}/{indexProblema}")
|
|
232
|
-
# with open(f"{OutputDir}/{indexProblema}", "wb") as new:
|
|
233
|
-
# pickle.dump(new_object, new)
|
|
234
558
|
|
|
235
559
|
def saveTaillardStandardFile(self, path):
|
|
236
560
|
os.makedirs("/".join(path.split("/")[:-1]),exist_ok=True)
|
|
@@ -460,11 +784,6 @@ class JSP:
|
|
|
460
784
|
if operation > 0 and operation < self.numMchs - 1:
|
|
461
785
|
graph.add_edge((job * self.numMchs + operation - 1, job * self.numMchs + operation))
|
|
462
786
|
|
|
463
|
-
# if __name__ == "__main__":
|
|
464
|
-
# jsp = JSP(jobs=5, machines=5)
|
|
465
|
-
# jsp.fill_random_values(speed=3, rddd=2, distribution="uniform", seed=1234)
|
|
466
|
-
# jsp.saveTaillardStandardFile("./output_taillard.txt")
|
|
467
|
-
|
|
468
787
|
|
|
469
788
|
|
|
470
789
|
#################################################################################
|
|
@@ -585,16 +904,16 @@ class FJSP(JSP):
|
|
|
585
904
|
"energy": str(energy.flatten()).replace(" ", ", ")
|
|
586
905
|
}
|
|
587
906
|
if t == 1:
|
|
588
|
-
replace_data["releaseDate"] = str([int(data.ReleaseDueDate[job, 0]) for job in range(data.numJobs)])
|
|
589
|
-
replace_data["dueDate"] = str([int(data.ReleaseDueDate[job, 1]) for job in range(data.numJobs)])
|
|
907
|
+
replace_data["releaseDate"] = str([int(data.ReleaseDueDate[job, 0]) for job in range(data.numJobs)]).replace(" ", ",")
|
|
908
|
+
replace_data["dueDate"] = str([int(data.ReleaseDueDate[job, 1]) for job in range(data.numJobs)]).replace(" ", ",")
|
|
590
909
|
elif t == 2:
|
|
591
|
-
replace_data["releaseDate"] = data.ReleaseDueDate[:, :, 0].flatten()
|
|
592
|
-
replace_data["dueDate"] = data.ReleaseDueDate[:, :, 1].flatten()
|
|
910
|
+
replace_data["releaseDate"] = str(data.ReleaseDueDate[:, :, 0].flatten()).replace(" ", ",")
|
|
911
|
+
replace_data["dueDate"] = str(data.ReleaseDueDate[:, :, 1].flatten()).replace(" ", ",")
|
|
593
912
|
|
|
594
913
|
for job in range(data.numJobs):
|
|
595
914
|
for i, prioridad in enumerate(range(data.numMchs)):
|
|
596
915
|
precedence[job, data.Orden[job, prioridad]] = i
|
|
597
|
-
replace_data["precedence"] = str(precedence.flatten()).replace(" ", ",
|
|
916
|
+
replace_data["precedence"] = str(precedence.flatten()).replace(" ", ",")
|
|
598
917
|
|
|
599
918
|
replace_data["available_machines"] = str(data.available_machines.flatten()).replace(" ", ", ")
|
|
600
919
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
IGJSP/generador.py,sha256=
|
|
1
|
+
IGJSP/generador.py,sha256=nSPgsVbpR5YydbrkIOhkGmXbFCnkaIAkRu-ok-_BJpY,47603
|
|
2
2
|
IGJSP/main.py,sha256=Sia5Ss8O3HWBdshvPLJKUMaZIoQPHy6x8yzvojojPFo,2838
|
|
3
3
|
IGJSP/Minizinc/Models/RD/JSP0.mzn,sha256=cfN_E3RQ6nBulGfaOOYTd-zAgA5SI6E2saDlYtKCflg,2282
|
|
4
4
|
IGJSP/Minizinc/Models/RD/JSP1.mzn,sha256=5B8cyw2WyKR8yEL1fFd0TaCAVhjPoxEJRJDPPEjJGEk,2840
|
|
@@ -12,7 +12,7 @@ IGJSP/Minizinc/Types/RD/FJSP/type2.dzn,sha256=Wz1MnkSL5GUPsbh1eq0leoaQRImkNqQqkX
|
|
|
12
12
|
IGJSP/Minizinc/Types/RD/JSP/type0.dzn,sha256=wNuPQkXBXPSpPaPz2WFhp4pGDgfSimtg4I93UfwC01Q,263
|
|
13
13
|
IGJSP/Minizinc/Types/RD/JSP/type1.dzn,sha256=Xbt9StzCgEqqh_HS9tWGrTVtu-OEnf5Yq5Ty91AkzoM,333
|
|
14
14
|
IGJSP/Minizinc/Types/RD/JSP/type2.dzn,sha256=L2nc7bPJEhyuaEwgw0ZCpC52CpVJILQU_WQdKn8GUZs,379
|
|
15
|
-
igjsp-1.
|
|
16
|
-
igjsp-1.
|
|
17
|
-
igjsp-1.
|
|
18
|
-
igjsp-1.
|
|
15
|
+
igjsp-1.1.0.dist-info/METADATA,sha256=q-mdPgQhQCvXKTtYbNMsDzgvR-oov4pe27Js_9Oeazo,10609
|
|
16
|
+
igjsp-1.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
17
|
+
igjsp-1.1.0.dist-info/licenses/LICENSE,sha256=f7RDRO-z_nMoooAya7NAb8sXtrHR6WnttYtyUc9fB-c,1116
|
|
18
|
+
igjsp-1.1.0.dist-info/RECORD,,
|
|
File without changes
|