PlatformFilters.java
package net.bmahe.genetics4j.gpu.spec;
import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.function.Predicate;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.Validate;
import net.bmahe.genetics4j.gpu.opencl.model.Platform;
import net.bmahe.genetics4j.gpu.opencl.model.PlatformProfile;
/**
* Utility class providing predicate-based filters for selecting OpenCL platforms in GPU-accelerated evolutionary algorithms.
*
* <p>PlatformFilters offers a fluent API for creating platform selection criteria based on platform characteristics
* such as profile type, supported extensions, and vendor capabilities. These filters are used to automatically
* select appropriate OpenCL platforms before device enumeration and selection.
*
* <p>Key functionality includes:
* <ul>
* <li><strong>Profile-based filtering</strong>: Select platforms by profile (FULL_PROFILE or EMBEDDED_PROFILE)</li>
* <li><strong>Extension filtering</strong>: Filter platforms based on supported OpenCL extensions</li>
* <li><strong>Logical combinations</strong>: Combine filters using AND and OR operations</li>
* <li><strong>Predicate composition</strong>: Build complex selection criteria from simple predicates</li>
* </ul>
*
* <p>Common usage patterns:
* <pre>{@code
* // Select platforms with full OpenCL profile
* Predicate<Platform> fullProfileFilter = PlatformFilters.ofProfile(PlatformProfile.FULL_PROFILE);
*
* // Select platforms supporting double precision arithmetic
* Predicate<Platform> fp64Filter = PlatformFilters.ofExtension("cl_khr_fp64");
*
* // Select platforms with multiple required extensions
* Set<String> requiredExtensions = Set.of("cl_khr_fp64", "cl_khr_global_int32_base_atomics");
* Predicate<Platform> extensionFilter = PlatformFilters.ofExtensions(requiredExtensions);
*
* // Combine multiple criteria
* Predicate<Platform> advancedFilter = PlatformFilters.and(
* PlatformFilters.ofProfile(PlatformProfile.FULL_PROFILE),
* PlatformFilters.ofExtension("cl_khr_fp64")
* );
*
* // Apply filter to platform selection
* GPUEAExecutionContext context = GPUEAExecutionContext.builder()
* .platformFilters(fullProfileFilter)
* .build();
* }</pre>
*
* <p>Platform selection workflow:
* <ol>
* <li><strong>Platform enumeration</strong>: Discover all available OpenCL platforms</li>
* <li><strong>Filter application</strong>: Apply platform filters to candidate platforms</li>
* <li><strong>Platform validation</strong>: Validate filtered platforms meet requirements</li>
* <li><strong>Device discovery</strong>: Enumerate devices on selected platforms</li>
* </ol>
*
* <p>Filter criteria considerations:
* <ul>
* <li><strong>Profile compatibility</strong>: FULL_PROFILE platforms typically offer more features</li>
* <li><strong>Extension requirements</strong>: Filter for extensions required by algorithms</li>
* <li><strong>Vendor optimization</strong>: Consider vendor-specific optimizations and extensions</li>
* <li><strong>Version requirements</strong>: Ensure platforms support required OpenCL versions</li>
* </ul>
*
* <p>Performance considerations:
* <ul>
* <li><strong>Platform enumeration overhead</strong>: Filters are applied during platform discovery</li>
* <li><strong>Extension validation</strong>: Extension checks may have runtime overhead</li>
* <li><strong>Fallback strategies</strong>: Implement fallback filters for limited platform availability</li>
* <li><strong>Caching</strong>: Platform characteristics are typically static during execution</li>
* </ul>
*
* @see Platform
* @see PlatformProfile
* @see GPUEAExecutionContext
*/
public class PlatformFilters {
private PlatformFilters() {
}
/**
* Creates a predicate that filters platforms by the specified profile type.
*
* @param platformProfile the OpenCL profile type to filter for (FULL_PROFILE or EMBEDDED_PROFILE)
* @return predicate that returns true for platforms with the specified profile
* @throws IllegalArgumentException if platformProfile is null
*/
public static Predicate<Platform> ofProfile(final PlatformProfile platformProfile) {
Validate.notNull(platformProfile);
return (platform) -> platformProfile.equals(platform.profile());
}
/**
* Creates a predicate that filters platforms supporting the specified OpenCL extension.
*
* @param extension the OpenCL extension name to filter for (e.g., "cl_khr_fp64")
* @return predicate that returns true for platforms supporting the extension
* @throws IllegalArgumentException if extension is null or blank
*/
public static Predicate<Platform> ofExtension(final String extension) {
Validate.notBlank(extension);
return (platform) -> platform.extensions()
.contains(extension);
}
/**
* Creates a predicate that filters platforms supporting all specified OpenCL extensions.
*
* @param extensions set of OpenCL extension names that must all be supported
* @return predicate that returns true for platforms supporting all specified extensions
* @throws IllegalArgumentException if extensions is null
*/
public static Predicate<Platform> ofExtensions(final Set<String> extensions) {
Validate.notNull(extensions);
return (platform) -> CollectionUtils.containsAll(platform.extensions(), extensions);
}
/**
* Creates a predicate that returns true if any of the provided predicates return true (logical OR).
*
* @param predicates array of platform predicates to combine with OR logic
* @return predicate that returns true if any input predicate returns true
* @throws IllegalArgumentException if predicates is null or empty
*/
public static Predicate<Platform> or(@SuppressWarnings("unchecked") final Predicate<Platform>... predicates) {
Validate.notNull(predicates);
Validate.isTrue(predicates.length > 0);
return platform -> Arrays.stream(predicates)
.anyMatch(predicate -> predicate.test(platform));
}
/**
* Creates a predicate that returns true if any of the provided predicates return true (logical OR).
*
* @param predicates collection of platform predicates to combine with OR logic
* @return predicate that returns true if any input predicate returns true
* @throws IllegalArgumentException if predicates is null or empty
*/
public static Predicate<Platform> or(final Collection<Predicate<Platform>> predicates) {
Validate.notNull(predicates);
Validate.isTrue(predicates.size() > 0);
return platform -> predicates.stream()
.anyMatch(predicate -> predicate.test(platform));
}
/**
* Creates a predicate that returns true only if all provided predicates return true (logical AND).
*
* @param predicates array of platform predicates to combine with AND logic
* @return predicate that returns true only if all input predicates return true
* @throws IllegalArgumentException if predicates is null or empty
*/
public static Predicate<Platform> and(@SuppressWarnings("unchecked") final Predicate<Platform>... predicates) {
Validate.notNull(predicates);
Validate.isTrue(predicates.length > 0);
return platform -> Arrays.stream(predicates)
.allMatch(predicate -> predicate.test(platform));
}
/**
* Creates a predicate that returns true only if all provided predicates return true (logical AND).
*
* @param predicates collection of platform predicates to combine with AND logic
* @return predicate that returns true only if all input predicates return true
* @throws IllegalArgumentException if predicates is null or empty
*/
public static Predicate<Platform> and(final Collection<Predicate<Platform>> predicates) {
Validate.notNull(predicates);
Validate.isTrue(predicates.size() > 0);
return platform -> predicates.stream()
.allMatch(predicate -> predicate.test(platform));
}
}