File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -13,12 +13,12 @@ FJSPLIB is a Python package for reading and writing flexible job shop problem (F
1313The FJSPLIB format is as follows:
1414
1515``` sh
16- < num jobs> < num machines> < average operations per job >
16+ < num jobs> < num machines> < avg num machines per operation >
1717< num operations> * (< num machines> * (< machine idx> < duration> ))
1818...
1919```
2020
21- The first line contains data about the number of jobs, number machines and average number of operations per job .
21+ The first line contains data about the number of jobs, number machines and average number of machines that can process an operation .
2222The following lines each represent the job data, one line for each job.
2323These lines are each parsed as follows:
2424- The first number denotes the number of operations for this job.
Original file line number Diff line number Diff line change 1+ from dataclasses import dataclass
2+
3+
4+ @dataclass
5+ class Instance :
6+ """
7+ The FJSPLIB instance data.
8+
9+ Parameters
10+ ----------
11+ num_jobs
12+ The number of jobs.
13+ num_machines
14+ The number of machines.
15+ num_operations
16+ The number of operations.
17+ jobs
18+ A list of job data, each job consisting of a list of operations.
19+ Operations are list of tuples, where each tuple consists of a machine
20+ index and a processing time.
21+ precedences
22+ A list of tuples consisting of two operation indices, representing the
23+ precedence relationship of two operations.
24+ """
25+
26+ num_jobs : int
27+ num_machines : int
28+ num_operations : int
29+ jobs : list [list [list [tuple [int , int ]]]]
30+ precedences : list [tuple [int , int ]]
Original file line number Diff line number Diff line change 1+ from .Instance import Instance as Instance
12from .read import read as read
3+ from .write import write as write
Original file line number Diff line number Diff line change 1- from dataclasses import dataclass
21from pathlib import Path
32from typing import Union
43
4+ from fjsplib .Instance import Instance
5+
56ProcessingData = list [tuple [int , int ]]
67Arc = tuple [int , int ]
78
89
9- @dataclass
10- class Instance :
11- """
12- The FJSPLIB instance data.
13-
14- Parameters
15- ----------
16- num_jobs
17- The number of jobs.
18- num_machines
19- The number of machines.
20- num_operations
21- The number of operations.
22- jobs
23- A list of job data, each job consisting of a list of operation indices.
24- precedences
25- A list of tuples consisting of two operation indices, representing the
26- precedence relationship of two operations.
27- """
28-
29- num_jobs : int
30- num_machines : int
31- num_operations : int
32- jobs : list [list [ProcessingData ]]
33- precedences : list [tuple [int , int ]]
34-
35-
3610def parse_job_line (line : list [int ]) -> list [ProcessingData ]:
3711 """
3812 Parses a FJSPLIB job data line of the following form:
Original file line number Diff line number Diff line change 1+ from pathlib import Path
2+ from typing import Union
3+
4+ from .Instance import Instance
5+
6+
7+ def write (where : Union [Path , str ], instance : Instance ):
8+ """
9+ Writes a problem instance to file in FJSPLIB format.
10+
11+ Parameters
12+ ----------
13+ where
14+ Location to write the instance to.
15+ instance
16+ The problem instance.
17+ """
18+ lines = []
19+
20+ # The flexibility is the average number of eligible machines per operation.
21+ num_eligible = sum ([len (task ) for ops in instance .jobs for task in ops ])
22+ flexibility = round (num_eligible / instance .num_operations , 1 )
23+
24+ metadata = f"{ instance .num_jobs } { instance .num_machines } { flexibility } "
25+ lines .append (metadata )
26+
27+ for operations in instance .jobs :
28+ job = [len (operations )]
29+
30+ for processing_data in operations :
31+ num_eligible = len (processing_data )
32+ job .append (num_eligible )
33+
34+ for machine , duration in processing_data :
35+ # Machine indices are 1-indexed in FJSPLIB.
36+ job .extend ([machine + 1 , duration ])
37+
38+ line = " " .join (str (num ) for num in job )
39+ lines .append (line )
40+
41+ formatted = "\n " .join (lines )
42+
43+ with open (where , "w" ) as fh :
44+ fh .write (formatted )
Original file line number Diff line number Diff line change 1- 2 3 2.2
1+ 2 3 1.7
221 2 1 1 2 2
332 1 1 1 2 3 1 2 1
Original file line number Diff line number Diff line change 1+ from pathlib import Path
2+
3+ from numpy .testing import assert_equal
4+
5+ from fjsplib .write import write
6+ from tests .utils import read
7+
8+
9+ def test_write (tmp_path : Path ):
10+ """
11+ Tests that ``write`` correctly writes an FJSPLIB instance to a file.
12+ """
13+ instance = read ("data/classic.fjs" )
14+ write (tmp_path / "classic.fjs" , instance )
15+
16+ expected = [
17+ "2 3 1.7" ,
18+ "1 2 1 1 2 2" ,
19+ "2 1 1 1 2 3 1 2 1" ,
20+ ]
21+ with open (tmp_path / "classic.fjs" , "r" ) as fh :
22+ assert_equal (fh .read (), "\n " .join (expected ))
You can’t perform that action at this time.
0 commit comments