A wrapper class for instance data
| 86 | |
| 87 | /// A wrapper class for instance data |
| 88 | class Spec { |
| 89 | protected: |
| 90 | /// Raw instance data |
| 91 | const int* data; |
| 92 | /// Lower and upper bound |
| 93 | int l, u; |
| 94 | /// Name |
| 95 | const char* n; |
| 96 | public: |
| 97 | /// Whether a valid specification has been found |
| 98 | bool valid(void) const { |
| 99 | return data != nullptr; |
| 100 | } |
| 101 | /// Return number of jobs |
| 102 | int jobs(void) const { |
| 103 | return data[0]; |
| 104 | } |
| 105 | /// Return number of machines |
| 106 | int machines(void) const { |
| 107 | return data[1]; |
| 108 | } |
| 109 | /// Return machine of step \a j in job \a i |
| 110 | int machine(int i, int j) const { |
| 111 | return data[2 + i*machines()*2 + j*2]; |
| 112 | } |
| 113 | /// Return duration of step \a j in job \a i |
| 114 | int duration(int i, int j) const { |
| 115 | return data[2 + i*machines()*2 + j*2 + 1]; |
| 116 | } |
| 117 | protected: |
| 118 | /// Find instance by name \a s |
| 119 | static const int* find(const char* s) { |
| 120 | for (int i=0; ::name[i] != nullptr; i++) |
| 121 | if (!strcmp(s,::name[i])) |
| 122 | return js[i]; |
| 123 | return nullptr; |
| 124 | } |
| 125 | /// Compute lower bound |
| 126 | int clower(void) const { |
| 127 | int l = 0; |
| 128 | Region r; |
| 129 | int* mach = r.alloc<int>(machines()); |
| 130 | for (int j=0; j<machines(); j++) |
| 131 | mach[j]=0; |
| 132 | for (int i=0; i<jobs(); i++) { |
| 133 | int job = 0; |
| 134 | for (int j=0; j<machines(); j++) { |
| 135 | mach[machine(i,j)] += duration(i,j); |
| 136 | job += duration(i,j); |
| 137 | } |
| 138 | l = std::max(l,job); |
| 139 | } |
| 140 | for (int j=0; j<machines(); j++) |
| 141 | l = std::max(l,mach[j]); |
| 142 | return l; |
| 143 | } |
| 144 | /// Compute naive upper bound |
| 145 | int cupper(void) const { |