• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SpiNNakerManchester / JavaSpiNNaker / 6310285782

26 Sep 2023 08:47AM UTC coverage: 36.367% (-0.5%) from 36.866%
6310285782

Pull #658

github

dkfellows
Merge branch 'master' into java-17
Pull Request #658: Update Java version to 17 and JEE to 9

1675 of 1675 new or added lines in 266 files covered. (100.0%)

8368 of 23010 relevant lines covered (36.37%)

0.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

56.06
/SpiNNaker-machine/src/main/java/uk/ac/manchester/spinnaker/machine/CoreSubsets.java
1
/*
2
 * Copyright (c) 2018 The University of Manchester
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package uk.ac.manchester.spinnaker.machine;
17

18
import static java.util.Collections.unmodifiableCollection;
19
import static java.util.Collections.unmodifiableSet;
20

21
import java.util.Collection;
22
import java.util.Iterator;
23
import java.util.Map;
24
import java.util.Objects;
25
import java.util.Set;
26
import java.util.TreeMap;
27

28
import jakarta.validation.Valid;
29
import uk.ac.manchester.spinnaker.utils.DoubleMapIterable;
30
import uk.ac.manchester.spinnaker.utils.MappableIterable;
31

32
/**
33
 * Represents a set of of {@link CoreLocation}s organised by chip. Each chip
34
 * location conceptually has a subset of cores that are members of this overall
35
 * {@code CoreSubsets}.
36
 *
37
 * @see <a href=
38
 *      "https://github.com/SpiNNakerManchester/SpiNNMachine/blob/master/spinn_machine/core_subsets.py">
39
 *      Python Version</a>
40
 * @author Christian-B
41
 */
42
public final class CoreSubsets implements MappableIterable<CoreLocation> {
43
        private final Map<@Valid ChipLocation,
44
                        Map<@ValidP Integer, @Valid CoreLocation>> locations;
45

46
        private boolean immutable;
47

48
        /**
49
         * Bases constructor which creates an empty set of CoreSubset(s).
50
         */
51
        public CoreSubsets() {
1✔
52
                locations = new TreeMap<>();
1✔
53
                immutable = false;
1✔
54
        }
1✔
55

56
        /**
57
         * Constructor which adds a single location.
58
         *
59
         * @param location
60
         *            The location of the processor to add.
61
         */
62
        public CoreSubsets(HasCoreLocation location) {
63
                this();
×
64
                addCore(location.asCoreLocation());
×
65
        }
×
66

67
        /**
68
         * Constructor which adds the locations.
69
         *
70
         * @param locations
71
         *            The location of all processors to add.
72
         */
73
        public CoreSubsets(Iterable<CoreLocation> locations) {
74
                this();
×
75
                addCores(locations);
×
76
        }
×
77

78
        /**
79
         * Adds the core Location.
80
         * <p>
81
         * This method uses set semantics so attempts to add a core/processor that
82
         * is already in the subset are silently ignored.
83
         *
84
         * @param core
85
         *            Location (x, y, p) to add.
86
         * @throws IllegalStateException
87
         *             If the subsets have been set immutable. For example because a
88
         *             hash-code has been generated,
89
         */
90
        public void addCore(CoreLocation core) {
91
                if (immutable) {
1✔
92
                        throw new IllegalStateException("The subsets is immutable. "
1✔
93
                                        + "Possibly because a hashcode has been generated.");
94
                }
95
                getOrCreate(core.asChipLocation()).put(core.getP(), core);
1✔
96
        }
1✔
97

98
        /**
99
         * Adds the core location, creating a new subset if required.
100
         * <p>
101
         * This method uses set semantics so attempts to add a core/processor that
102
         * is already in the subset are silently ignored.
103
         *
104
         * @param x
105
         *            X coordinate of chip
106
         * @param y
107
         *            Y coordinate of chip
108
         * @param p
109
         *            P coordinate/ processor ID
110
         * @throws IllegalStateException
111
         *             If the subsets have been set immutable. For example because a
112
         *             hash-code has been generated,
113
         */
114
        public void addCore(int x, int y, int p) {
115
                addCore(new ChipLocation(x, y), p);
1✔
116
        }
1✔
117

118
        /**
119
         * Adds the processor for this chip, creating a new subset if required.
120
         * <p>
121
         * This method uses set semantics so attempts to add a core/processor that
122
         * is already in the subset are silently ignored.
123
         *
124
         * @param chip
125
         *            Chip key of CoreSubset to add to.
126
         * @param p
127
         *            P coordinate/ processor ID.
128
         * @throws IllegalStateException
129
         *             If the subsets have been set immutable. For example because a
130
         *             hashcode has been generated,
131
         */
132
        public void addCore(ChipLocation chip, int p) {
133
                if (immutable) {
1✔
134
                        throw new IllegalStateException("The subsets is immutable. "
1✔
135
                                        + "Possibly because a hashcode has been generated.");
136
                }
137
                getOrCreate(chip).put(p, new CoreLocation(chip, p));
1✔
138
        }
1✔
139

140
        /**
141
         * Adds the processors for this chip, creating a new subset if required.
142
         * <p>
143
         * This method uses set semantics so attempts to add a core/processor that
144
         * is already in the subset are silently ignored.
145
         *
146
         * @param chip
147
         *            Chip key of CoreSubset to add to.
148
         * @param processors
149
         *            p coordinates/ processor IDs.
150
         * @throws IllegalStateException
151
         *             If the subsets have been set immutable. For example because a
152
         *             hash-code has been generated,
153
         */
154
        public void addCores(ChipLocation chip, Iterable<Integer> processors) {
155
                if (immutable) {
1✔
156
                        throw new IllegalStateException("The subsets is immutable. "
1✔
157
                                        + "Possibly because a hashcode has been generated.");
158
                }
159
                var map = getOrCreate(chip);
1✔
160
                for (var p : processors) {
1✔
161
                        map.put(p, new CoreLocation(chip, p));
1✔
162
                }
1✔
163
        }
1✔
164

165
        /**
166
         * Adds the processors for this chip, creating a new subset if required.
167
         * <p>
168
         * This method uses set semantics so attempts to add a core/processor that
169
         * is already in the subset are silently ignored.
170
         *
171
         * @param x
172
         *            x coordinate of chip
173
         * @param y
174
         *            y coordinate of chip
175
         * @param processors
176
         *            p coordinates/ processor IDs.
177
         * @throws IllegalStateException
178
         *             If the subsets have been set immutable. For example because a
179
         *             hash-code has been generated,
180
         */
181
        public void addCores(int x, int y, Iterable<Integer> processors) {
182
                addCores(new ChipLocation(x, y), processors);
1✔
183
        }
1✔
184

185
        /**
186
         * Adds the locations into this one.
187
         * <p>
188
         * This method uses set semantics so attempts to add a core/processor that
189
         * is already in the subset are silently ignored.
190
         *
191
         * @param locations
192
         *            the locations to add.
193
         */
194
        public void addCores(Iterable<CoreLocation> locations) {
195
                for (var location : locations) {
×
196
                        addCore(location);
×
197
                }
×
198
        }
×
199

200
        /**
201
         * Obtain the set of processor IDs for a given chip.
202
         *
203
         * @param chip
204
         *            Coordinates of a chip
205
         * @return The subset of a chip or {@code null} if there is no subset.
206
         *         Modifiable!
207
         */
208
        private Map<Integer, CoreLocation> getOrCreate(ChipLocation chip) {
209
                return locations.computeIfAbsent(chip, __ -> new TreeMap<>());
1✔
210
        }
211

212
        /**
213
         * The total number of processors that are in these core subsets.
214
         *
215
         * @return The sum of the individual subset sizes.
216
         */
217
        public int size() {
218
                return locations.values().stream().mapToInt(Map::size).sum();
1✔
219
        }
220

221
        /**
222
         * Whether there are any processors in these core subsets.
223
         *
224
         * @return {@code true} when all the subsets are empty.
225
         */
226
        public boolean isEmpty() {
227
                return locations.values().stream().allMatch(Map::isEmpty);
1✔
228
        }
229

230
        /**
231
         * Determine if the chip with coordinates (x, y) is in the subset.
232
         * <p>
233
         * <strong>Note:</strong> An empty subset mapped to the chip is ignored.
234
         *
235
         * @param chip
236
         *            Coordinates to check
237
         * @return True if and only if there is a none empty Subset for this Chip.
238
         */
239
        public boolean isChip(ChipLocation chip) {
240
                return !locations.getOrDefault(chip, Map.of()).isEmpty();
1✔
241
        }
242

243
        /**
244
         * Determine if there is a chip with coordinates (x, y) in the subset, which
245
         * has a core with the given ID in the subset.
246
         *
247
         * @param core
248
         *            x, y and p coordinates
249
         * @return True if and only if there is a core with these coordinates
250
         */
251
        public boolean isCore(CoreLocation core) {
252
                return locations.getOrDefault(core.asChipLocation(), Map.of())
1✔
253
                                .containsValue(core);
1✔
254
        }
255

256
        /**
257
         * Generate a hash-code for these subsets.
258
         * <p>
259
         * Two {@code CoreSubsets} that have the same subsets (and are therefore
260
         * considered equals) will generate the same hash-code.
261
         * <p>
262
         * To guarantee consistency over time, once a hash-code is requested the
263
         * {@code CoreSubsets} and all its subsets will be made immutable and any
264
         * further add calls will raise an exception.
265
         *
266
         * @return integer to use as the hash-code.
267
         */
268
        @Override
269
        public int hashCode() {
270
                immutable = true;
1✔
271
                int hash = 7;
1✔
272
                for (var subset : locations.values()) {
1✔
273
                        for (var location : subset.values()) {
1✔
274
                                hash = 89 * hash + location.hashCode();
1✔
275
                        }
1✔
276
                }
1✔
277
                return hash;
1✔
278
        }
279

280
        /**
281
         * Indicates whether some other object is "equal to" this one. It is
282
         * reflexive, symmetric and transitive. It is consistent provided no core or
283
         * subset has been added.
284
         * <p>
285
         * Unlike {@link #hashCode()}, a call to equals does <em>not</em> effect
286
         * mutability.
287
         *
288
         * @param obj
289
         *            Other object to compare to.
290
         * @return True if and only if {@code obj} is another {@code CoreSubsets}
291
         *         with exactly the same subsets.
292
         */
293
        @Override
294
        public boolean equals(Object obj) {
295
                return (obj instanceof CoreSubsets other)
×
296
                                && Objects.equals(locations, other.locations);
×
297
        }
298

299
        @Override
300
        public String toString() {
301
                return locations.toString();
×
302
        }
303

304
        /**
305
         * Returns a new {@code CoreSubsets} which is an intersect of this and the
306
         * other.
307
         *
308
         * @param other
309
         *            A second {@code CoreSubsets} with possibly overlapping cores.
310
         * @return A new {@code CoreSubsets} object with only the cores present in
311
         *         both. Therefore the result may be empty.
312
         */
313
        public CoreSubsets intersection(CoreSubsets other) {
314
                var results = new CoreSubsets();
×
315
                locations.forEach((chip, locs) -> {
×
316
                        var otherSubset = other.locations.get(chip);
×
317
                        if (otherSubset != null) {
×
318
                                locs.forEach((__, location) -> {
×
319
                                        if (otherSubset.containsValue(location)) {
×
320
                                                results.addCore(location);
×
321
                                        }
322
                                });
×
323
                        }
324
                });
×
325
                return results;
×
326
        }
327

328
        /**
329
         * Returns the {@link ChipLocation}s for which there is at least one
330
         * {@link CoreLocation} in the subsets.
331
         * <p>
332
         * The order of the locations is guaranteed to be the natural order.
333
         *
334
         * @return An ordered set of chips.
335
         */
336
        public Set<ChipLocation> getChips() {
337
                return unmodifiableSet(locations.keySet());
×
338
        }
339

340
        @Override
341
        public Iterator<CoreLocation> iterator() {
342
                return new DoubleMapIterable<>(locations).iterator();
×
343
        }
344

345
        /**
346
         * Provides the {@link CoreLocation}s for just a single chip.
347
         * <p>
348
         * This will be an empty list when {@link #isChip(ChipLocation)} returns
349
         * {@code false}.
350
         *
351
         * @param chip
352
         *            coordinates of the chip
353
         * @return Unmodifiable (possibly empty) collection of CoreLocation
354
         */
355
        public Collection<CoreLocation> coreByChip(ChipLocation chip) {
356
                var l = locations.getOrDefault(chip, Map.of());
×
357
                return unmodifiableCollection(l.values());
×
358
        }
359

360
        /**
361
         * Provides the processor identifiers for just a single chip.
362
         * <p>
363
         * This will be an empty list when {@link #isChip(ChipLocation)} returns
364
         * {@code false}.
365
         *
366
         * @param chip
367
         *            coordinates of the chip
368
         * @return Unmodifiable (possibly empty) collection of processor identifiers
369
         */
370
        public Set<Integer> pByChip(ChipLocation chip) {
371
                var l = locations.getOrDefault(chip, Map.of());
×
372
                return unmodifiableSet(l.keySet());
×
373
        }
374
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc