From f52396427043b3aceb0ccce6e752fb116e495227 Mon Sep 17 00:00:00 2001
From: Emil Karlsson <emil.karlssson@liu.se>
Date: Thu, 17 Feb 2022 21:13:23 +0100
Subject: [PATCH] Instance creation script corrected

- Incorrect file for instance file generation was previously added
---
 README.md              |   1 +
 instances.py           | 158 +++++++++++++++++++++++------------------
 segmented_instances.sh |  32 ++++-----
 3 files changed, 106 insertions(+), 85 deletions(-)

diff --git a/README.md b/README.md
index a9043f7..29b51b0 100644
--- a/README.md
+++ b/README.md
@@ -41,6 +41,7 @@ Instance set II is generated according to description in E. Coban and J. N. Hook
 The instance generator is available in [instances.py](instances.py) and we have used Python 3.8 to generate them. To generate all instances used in our article perform the following command.
 
 ```bash
+>>> # source virtual environment with python3.8
 >>> sh segmented_instances.sh
 ```
 
diff --git a/instances.py b/instances.py
index 03d76dd..84ae98a 100644
--- a/instances.py
+++ b/instances.py
@@ -2,6 +2,43 @@
 A script to generate instances for the simple job shop problem with
 fixed cost according to the method described in REFERENCE.
 
+
+alpha * R
+gamma1 * alpha * R
+gamma2 * alpha * R
+beta (dj - rj)
+
+Tight
+
+alpha = 0.5
+gamma1 = 0.5
+gamma2 = 1.0
+
+- 60: beta = 1 / 20
+- 80: beta = 1 / 20
+- 100: beta = 1 / 24
+- 120: beta = 1 / 28
+- 140: beta = 1 / 32
+- 160: beta = 1 / 32?
+- 180: beta = 1 / 32?
+- 200: beta = 1 / 32?
+
+Wide
+
+alpha = 0.5
+gamma1 = 0.25
+gamma2 = 1.0
+beta = 0.035
+
+- 60
+- 80
+- 100
+- 120
+- 140
+- 160
+- 180
+- 200
+
 Usage example: python instances.py test_file.dat
 
 """
@@ -20,105 +57,88 @@ from collections import namedtuple
 @dataclass(frozen=True, order=True)
 class Job:
     ID: int
-    release_time: int
-    deadline: int
-
+    release_time: float
+    deadline: float
+    processing_time: float
 
-@dataclass(frozen=True)
-class MachineJob:
-    duration: int
-    resource: int
-    cost: int
 
-
-@dataclass(frozen=True)
-class Machine:
+@dataclass(frozen=True, order=True)
+class Segment:
     ID: int
-    resource_limit: int
-
+    start: float
+    end: float
 
 
 def preparse_line(line):
     return "".join(i for i in line.replace("<", "").replace("\n", "").replace(">", "").replace("[", "").replace("]", "") if i.isdigit() or i == " ")
 
 
-def generate_instance(no_jobs=None, no_machines=None, alpha=1/3, release_date_on=False):
+def generate_instance(no_jobs, alpha, gamma1, gamma2, beta, segments_percentage, time_scale):
+    TIME_SCALE = time_scale
+    segments = list()
+    assert no_jobs % round(1/segments_percentage) == 0
+    no_segments = round(segments_percentage * no_jobs)  # Always ten percent of all jobs
+    R = no_segments
+    for segment_id in range(no_segments):
+        start = round(segment_id * TIME_SCALE)
+        end = round((segment_id + 1) * TIME_SCALE)
+        segment = Segment(segment_id, start, end)
+        segments.append(segment)
+
     jobs = list()
-    machines = list()
-    machine_job_info = dict()
-    capacity_limit = 10  # For all instances
-    L = 5 * no_jobs * (no_machines + 1) / no_machines
     for job_id in range(no_jobs):
-        capacity_usage = random.randint(1, 10)  # (0, 10) -> same for all machines
-        max_processing_time = 0
-        for machine_id in range(no_machines):
-            i = machine_id + 1
-            processing_time = random.randint(i, 10 * i)
-            max_processing_time = max(max_processing_time, processing_time)
-            cost = random.randint(2 * (no_machines - i + 1), 20 * (no_machines - i + 1))
-            machine_job = MachineJob(processing_time, capacity_usage, cost)
-            machine_job_info[machine_id, job_id] = machine_job
-        if release_date_on:
-            release_date = random.randrange(0, max_processing_time)  # Same for all jobs
-            deadline = release_date + max_processing_time + random.randrange(0, max_processing_time)  # Same for all jobs
-        else:
-            release_date = 0
-            deadline = alpha * L
-        job = Job(job_id, release_date, deadline)
+        release_time = random.uniform(0, alpha * R)
+        deadline = release_time + random.uniform(gamma1 * alpha * R, gamma2 * alpha * R)
+        processing_time = random.uniform(0, beta * (deadline - release_time))
+        job = Job(job_id, round(TIME_SCALE * release_time), round(TIME_SCALE * deadline), round(TIME_SCALE * processing_time))
         jobs.append(job)
-    for machine_id in range(no_machines):
-        machine = Machine(machine_id, capacity_limit)
-        machines.append(machine)
 
-    return jobs, machines, machine_job_info
+    return tuple(jobs), tuple(segments)
 
 
-def instance_to_str(jobs, machines, machine_job_info):
+def instance_to_str(jobs: Tuple[Job], segments: Tuple[Segment]):
     instance_str = ""
     instance_str += f"JobCount = {len(jobs)} ;\n"
-    instance_str += f"MachineCount = {len(machines)} ;\n"
-    instance_str += "machjob  = [\n"
+    instance_str += f"SegmentCount = {len(segments)} ;\n"
+    instance_str += "Job  = [\n"
     
-    for machine in machines:
-        machine_str = "["
-        for job in jobs:
-            machine_job = machine_job_info[machine.ID, job.ID]
-            job_str = f"<{machine_job.duration} {machine_job.resource} {machine_job.cost}> "
-            machine_str += job_str
-        machine_str += "]\n"
-        instance_str += machine_str
+    machine_str = "["
+    for job in jobs:
+        job_str = f"<{job.release_time} {job.deadline} {job.processing_time}> "
+        machine_str += job_str
+    machine_str += "]\n"
+    instance_str += machine_str
     instance_str += "];\n"
 
-    limit_str = "Limit = ["
-    for machine in machines:
-        limit_str += f"{machine.resource_limit} "
-    limit_str += "];\n"
-    instance_str += limit_str
-
-    job_str = "Job = ["
-    for job in jobs:
-        job_str += f"<{job.release_time} {job.deadline}> "
-    job_str += "]\n"
-    instance_str += job_str
+    segment_str = "Segment = ["
+    for segment in segments:
+        segment_str += f"<{segment.start} {segment.end} > "
+    segment_str += "];\n"
+    instance_str += segment_str
 
     return instance_str
 
 
+# A segment is between two consecutive integers?
 if __name__ == "__main__":
     # Argument parser
-    parser = argparse.ArgumentParser(description='Generate an simple job shop problem with fixed cost instance')
-    parser.add_argument('-r', '--release_time', action='store_true', help='Specifies if the tasks should have unique release times.')
-    parser.add_argument('-m', '--no_machines', type=int, help='The number of machines', default=3)
+    parser = argparse.ArgumentParser(description='Generate a segmented feasibility problem')
+    parser.add_argument('-a', '--alpha', type=float, help='?', default=0.5)
+    parser.add_argument('-g1', '--gamma1', type=float, help='Control the lower limit of time windows', default=0.5)
+    parser.add_argument('-g2', '--gamma2', help="Control the upper limit of time windows", default=1, type=float)
     parser.add_argument('-s', '--seed', help="The seed used for randomisation", default=0, type=int)
-    parser.add_argument('-j', '--no_jobs', help="The number of jobs on the instance", default=20, type=int)
-    parser.add_argument('-a', '--alpha', help="Selection of parameter alpha", type=float, default=0.3)
+    parser.add_argument('-j', '--no_jobs', help="The number of jobs on the instance", default=60, type=int)
+    parser.add_argument('-b', '--beta', help="Control processing time relative time windows width", type=float, default=0.035)
+    parser.add_argument('-t', '--time_scale', help="Control the time scale", type=float, default=100)
+    parser.add_argument('--segments', help="Specify the percentage of jobs that are segments", type=float, default=0.1)
     parser.add_argument('instance', help='Path to instance that is created', type=str)
     args = parser.parse_args()
 
     random.seed(args.seed)
-    jobs, machines, machine_job_info = generate_instance(args.no_jobs, args.no_machines, args.alpha, args.release_time)
-    instance_str = instance_to_str(jobs, machines, machine_job_info)
+    jobs, segments = generate_instance(args.no_jobs, args.alpha, args.gamma1, args.gamma2, args.beta, args.segments, args.time_scale)
+    instance_str = instance_to_str(jobs, segments)
 
     print(instance_str)
-    with open(args.instance, 'w') as instance_file:
-        instance_file.write(instance_str)
+    if args.instance != 'dry':
+        with open(args.instance, 'w') as instance_file:
+            instance_file.write(instance_str)
diff --git a/segmented_instances.sh b/segmented_instances.sh
index 2a2b587..bdb8871 100644
--- a/segmented_instances.sh
+++ b/segmented_instances.sh
@@ -2,25 +2,25 @@
 echo "Tight windows"
 for SEED in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 do
-    python instances_segmented.py "sms_segmented_instances_new/tight60j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.5 --seed $SEED -j 60 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/tight80j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.45 --seed $SEED -j 80 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/tight100j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.4 --seed $SEED -j 100 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/tight120j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.35 --seed $SEED -j 120 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/tight140j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.3 --seed $SEED -j 140 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/tight160j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.25 --seed $SEED -j 160 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/tight180j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.2 --seed $SEED -j 180 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/tight200j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.15 --seed $SEED -j 200 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/tight60j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.5 --seed $SEED -j 60 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/tight80j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.45 --seed $SEED -j 80 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/tight100j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.4 --seed $SEED -j 100 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/tight120j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.35 --seed $SEED -j 120 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/tight140j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.3 --seed $SEED -j 140 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/tight160j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.25 --seed $SEED -j 160 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/tight180j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.2 --seed $SEED -j 180 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/tight200j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.2 --beta 0.15 --seed $SEED -j 200 -t 1000 --segments 0.10
 done
 
 echo "Wide windows"
 for SEED in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 do
-    python instances_segmented.py "sms_segmented_instances_new/wide60j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.5 --seed $SEED -j 60 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/wide80j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.45 --seed $SEED -j 80 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/wide100j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.4 --seed $SEED -j 100 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/wide120j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.35 --seed $SEED -j 120 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/wide140j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.30 --seed $SEED -j 140 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/wide160j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.25 --seed $SEED -j 160 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/wide180j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.20 --seed $SEED -j 180 -t 1000 --segments 0.10
-    python instances_segmented.py "sms_segmented_instances_new/wide200j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.15 --seed $SEED -j 200 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/wide60j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.5 --seed $SEED -j 60 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/wide80j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.45 --seed $SEED -j 80 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/wide100j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.4 --seed $SEED -j 100 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/wide120j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.35 --seed $SEED -j 120 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/wide140j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.30 --seed $SEED -j 140 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/wide160j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.25 --seed $SEED -j 160 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/wide180j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.20 --seed $SEED -j 180 -t 1000 --segments 0.10
+    python3.8 instances.py "sms_sdspmtw__instance_set_ii/wide200j1000s$SEED.dat" --gamma1 0.0 --gamma2 0.5 --beta 0.15 --seed $SEED -j 200 -t 1000 --segments 0.10
 done
-- 
GitLab