https://github.com/n1crack/subset-finder
A Laravel collection-powered PHP package, enables efficient extraction of subsets from collections, ideal for discount calculations and inventory management.
https://github.com/n1crack/subset-finder
collection discount ecommerce php subset-selection
Last synced: 5 months ago
JSON representation
A Laravel collection-powered PHP package, enables efficient extraction of subsets from collections, ideal for discount calculations and inventory management.
- Host: GitHub
- URL: https://github.com/n1crack/subset-finder
- Owner: n1crack
- License: mit
- Created: 2024-02-06T08:02:16.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2026-01-12T18:10:50.000Z (6 months ago)
- Last Synced: 2026-01-12T23:52:47.826Z (6 months ago)
- Topics: collection, discount, ecommerce, php, subset-selection
- Language: PHP
- Homepage:
- Size: 104 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE.md
Awesome Lists containing this project
README
# SubsetFinder PHP Package
[](https://packagist.org/packages/ozdemir/subset-finder)
[](https://github.com/n1crack/subset-finder/actions)
[](https://github.com/n1crack/subset-finder/blob/main/LICENSE.md)
A powerful and flexible PHP package for efficiently finding subsets within collections based on quantity criteria. Built with Laravel collections and optimized for performance, memory efficiency, and developer experience.
## Features
- **High Performance**: Optimized algorithms with configurable memory limits
- **Flexible Configuration**: Multiple configuration profiles for different use cases
- **Performance Monitoring**: Built-in metrics and logging capabilities
- **Robust Error Handling**: Comprehensive validation and meaningful error messages
- **Type Safety**: Full PHP 8.1+ type support with strict validation
- **Comprehensive Testing**: 100% test coverage with Pest PHP
- **Laravel Integration**: Service provider, facade, and trait support
- **Memory Efficient**: Optional lazy evaluation for large datasets
## Installation
```bash
composer require ozdemir/subset-finder
```
### Laravel Integration
The package automatically registers with Laravel. If you need to publish the configuration:
```bash
php artisan vendor:publish --tag=subset-finder-config
```
## Quick Start
### Basic Usage
```php
use Ozdemir\SubsetFinder\Subset;
use Ozdemir\SubsetFinder\SubsetCollection;
use Ozdemir\SubsetFinder\SubsetFinder;
use Ozdemir\SubsetFinder\SubsetFinderConfig;
// Define your collection and subset criteria
$collection = collect([
new Product(id: 1, quantity: 11, price: 15),
new Product(id: 2, quantity: 6, price: 5),
new Product(id: 3, quantity: 6, price: 5),
]);
$subsetCollection = new SubsetCollection([
Subset::of([1, 2])->take(5), // Find 5 items from products 1 and 2
Subset::of([3])->take(2), // Find 2 items from product 3
]);
// Create and configure SubsetFinder
$config = new SubsetFinderConfig(
idField: 'id',
quantityField: 'quantity',
sortField: 'price', // Sort by price (ascending)
sortDescending: false
);
$subsetFinder = new SubsetFinder($collection, $subsetCollection, $config);
$subsetFinder->solve();
// Get results
$foundSubsets = $subsetFinder->getFoundSubsets();
$remaining = $subsetFinder->getRemaining();
$maxSubsets = $subsetFinder->getSubsetQuantity();
```
### Using Configuration Profiles
```php
// For large datasets (512MB memory, lazy evaluation enabled)
$subsetFinder = new SubsetFinder(
$collection,
$subsetCollection,
SubsetFinderConfig::forLargeDatasets()
);
// For performance (64MB memory, lazy evaluation disabled)
$subsetFinder = new SubsetFinder(
$collection,
$subsetCollection,
SubsetFinderConfig::forPerformance()
);
// For balanced approach (256MB memory, lazy evaluation enabled)
$subsetFinder = new SubsetFinder(
$collection,
$subsetCollection,
SubsetFinderConfig::forBalanced()
);
```
### Using the Facade
```php
use Ozdemir\SubsetFinder\Facades\SubsetFinder;
// Create with default configuration
$subsetFinder = SubsetFinder::create($collection, $subsetCollection);
// Create with specific profile
$subsetFinder = SubsetFinder::forLargeDatasets($collection, $subsetCollection);
$subsetFinder = SubsetFinder::forPerformance($collection, $subsetCollection);
```
### Using the Trait
```php
use Ozdemir\SubsetFinder\Traits\HasSubsetOperations;
class ProductCollection extends Collection
{
use HasSubsetOperations;
}
$products = new ProductCollection([...]);
// Find subsets directly on the collection
$subsetFinder = $products->findSubsets($subsetCollection);
// Use profiles
$subsetFinder = $products->findSubsetsWithProfile($subsetCollection, 'large_datasets');
// Check feasibility
if ($products->canSatisfySubsets($subsetCollection)) {
// Proceed with subset creation
}
```
## Use Cases
### E-commerce Bundle Creation
```php
$products = collect([
new Product(id: 1, quantity: 100, price: 10), // T-shirt
new Product(id: 2, quantity: 50, price: 5), // Socks
new Product(id: 3, quantity: 25, price: 20), // Hat
]);
$bundles = new SubsetCollection([
Subset::of([1, 2])->take(2), // T-shirt + Socks bundle
Subset::of([1, 3])->take(1), // T-shirt + Hat bundle
]);
$subsetFinder = new SubsetFinder($products, $bundles);
$subsetFinder->solve();
// Create 25 T-shirt + Socks bundles
// Create 25 T-shirt + Hat bundles
// Remaining: 25 T-shirts, 0 socks, 0 hats
```
### Inventory Management
```php
$inventory = collect([
new Item(id: 'A', quantity: 100, category: 'electronics'),
new Item(id: 'B', quantity: 200, category: 'clothing'),
new Item(id: 'C', quantity: 150, category: 'books'),
]);
$orders = new SubsetCollection([
Subset::of(['A', 'B'])->take(10), // Electronics + Clothing order
Subset::of(['C'])->take(5), // Books order
]);
$subsetFinder = new SubsetFinder($inventory, $orders);
$subsetFinder->solve();
```
## Configuration
### Environment Variables
```env
SUBSET_FINDER_MAX_MEMORY=256M
SUBSET_FINDER_LAZY_EVALUATION=true
SUBSET_FINDER_LOGGING=true
SUBSET_FINDER_LOG_CHANNEL=subset-finder
SUBSET_FINDER_LOG_LEVEL=info
```
### Configuration File
```php
// config/subset-finder.php
return [
'defaults' => [
'id_field' => 'id',
'quantity_field' => 'quantity',
'sort_field' => 'id',
'sort_descending' => false,
'max_memory_usage' => env('SUBSET_FINDER_MAX_MEMORY', 128 * 1024 * 1024),
'enable_lazy_evaluation' => env('SUBSET_FINDER_LAZY_EVALUATION', true),
'enable_logging' => env('SUBSET_FINDER_LOGGING', false),
],
'profiles' => [
'large_datasets' => [
'max_memory_usage' => 512 * 1024 * 1024,
'enable_lazy_evaluation' => true,
'enable_logging' => true,
],
'performance' => [
'max_memory_usage' => 64 * 1024 * 1024,
'enable_lazy_evaluation' => false,
'enable_logging' => false,
],
],
];
```
## Performance Monitoring
```php
$subsetFinder = new SubsetFinder($collection, $subsetCollection);
$subsetFinder->solve();
// Get performance metrics
$metrics = $subsetFinder->getPerformanceMetrics();
// [
// 'execution_time_ms' => 45.23,
// 'memory_peak_mb' => 12.5,
// 'memory_increase_mb' => 8.2,
// 'collection_size' => 1000,
// 'subset_count' => 5,
// 'found_subsets_count' => 5,
// 'remaining_items_count' => 50
// ]
// Check solution quality
$isOptimal = $subsetFinder->isOptimal(); // true if no remaining items
$efficiency = $subsetFinder->getEfficiencyPercentage(); // 95.2%
```
## Error Handling
```php
use Ozdemir\SubsetFinder\Exceptions\InvalidArgumentException;
use Ozdemir\SubsetFinder\Exceptions\InsufficientQuantityException;
try {
$subsetFinder = new SubsetFinder($collection, $subsetCollection);
$subsetFinder->solve();
} catch (InvalidArgumentException $e) {
// Handle invalid input (empty collection, invalid items, etc.)
Log::error('Invalid subset finder input: ' . $e->getMessage());
} catch (InsufficientQuantityException $e) {
// Handle insufficient quantities
Log::warning('Cannot create subsets: ' . $e->getMessage());
}
```
## Testing
```bash
# Run tests
composer test
# Run tests with coverage
composer test-coverage
# Run static analysis
composer analyse
```
## Performance Tips
1. **Use appropriate configuration profiles** for your dataset size
2. **Enable lazy evaluation** for large collections to reduce memory usage
3. **Monitor memory usage** and adjust `max_memory_usage` accordingly
4. **Use meaningful sort fields** to optimize subset selection
5. **Consider batch processing** for very large datasets
## Advanced Usage
### Custom Logging
```php
use Psr\Log\LoggerInterface;
class CustomLogger implements LoggerInterface
{
// Implement logger methods
}
$subsetFinder = new SubsetFinder(
$collection,
$subsetCollection,
$config,
new CustomLogger()
);
```
### Memory Management
```php
// Check memory before processing
if (memory_get_usage(true) > $config->maxMemoryUsage) {
throw new \Exception('Insufficient memory for processing');
}
// Process in batches for very large datasets
$batchSize = 1000;
foreach ($collection->chunk($batchSize) as $batch) {
// Process batch
}
```
## Contributing
Contributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
## License
This package is open-sourced software licensed under the [MIT License](LICENSE.md).
## Support
- **Documentation**: [GitHub Wiki](https://github.com/n1crack/subset-finder/wiki)
- **Issues**: [GitHub Issues](https://github.com/n1crack/subset-finder/issues)
- **Discussions**: [GitHub Discussions](https://github.com/n1crack/subset-finder/discussions)
## Roadmap
### ✅ **Redis Caching Support**
- **High-performance caching** with Redis integration
- **Memory-based fallback** when Redis is unavailable
- **Smart cache key generation** based on input data
- **Configurable TTL** and cache management
- **Automatic fallback** to memory cache on Redis failure
### ✅ **Parallel Processing**
- **Multi-process subset finding** for large datasets
- **Intelligent chunking** with optimal size calculation
- **System-aware process limits** based on CPU and memory
- **Simulated parallel processing** for development environments
- **Performance metrics** for parallel operations
### ✅ **Weighted Subset Selection**
- **Multi-criteria optimization** with configurable weights
- **Advanced constraint handling** (ranges, custom functions)
- **Efficiency scoring** and ranking algorithms
- **Statistical analysis** with quartiles and distributions
- **Real-world optimization** scenarios (e-commerce, inventory)
### 🔄 **In Development**
- [ ] Machine learning-based optimization
- [ ] GraphQL integration
- [ ] Performance benchmarking tools
- [ ] More configuration profiles