Skip to content

Validate Reference

The validate module provides validation classes to ensure lineups meet various constraints and requirements.

Available Validators

General Validation

DuplicatesValidate

Removes lineups that contain duplicate players.

Use case: Ensure no player appears multiple times in a lineup.

Key features: - Efficient duplicate detection using sorted arrays - Handles both internal duplicates (within lineup) and external duplicates (between lineups) - Optimized for large populations

FlexDuplicatesValidate

Validates that FLEX positions don't duplicate players already used in other positions.

Use case: Ensure FLEX players are truly additional and don't overlap with required positions.

Key features: - Vectorized approach for efficiency - Handles complex position mapping scenarios - Prevents invalid lineups where FLEX duplicates required positions

SalaryValidate

Ensures all lineups meet salary cap constraints.

Use case: Filter out lineups that exceed the salary cap.

Key features: - Fast salary calculation using numpy operations - Configurable salary cap - Efficient boolean indexing for filtering

Position Validation

PositionValidate

Validates that lineups meet position requirements (QB, RB, WR, TE, etc.).

Use case: Ensure lineups have the correct number of players at each position.

Key features: - Flexible position mapping support - FLEX position handling - Comprehensive position requirement checking

Parameters: - posmap: Position requirements (e.g., {'QB': 1, 'RB': 2, 'WR': 3, 'TE': 1, 'DST': 1, 'FLEX': 1}) - position_column: Column name for positions in player pool - flex_positions: Positions that can fill FLEX slots (default: ('RB', 'WR', 'TE'))

PositionValidateOptimized

Optimized version of position validation using vectorized operations.

Use case: Same as PositionValidate but with better performance for large populations.

Key features: - Vectorized validation for better performance - Pre-computed position arrays for fast lookup - Same functionality as PositionValidate with speed improvements

Usage Examples

Basic Validation Setup

from pangadfs.validate import DuplicatesValidate, SalaryValidate, PositionValidate

# Set up validators
validators = [
    DuplicatesValidate(),
    SalaryValidate(),
    PositionValidate()
]

# Apply validation in sequence
for validator in validators:
    population = validator.validate(
        population=population,
        salaries=salaries,
        salary_cap=50000,
        pool=player_pool,
        posmap={'QB': 1, 'RB': 2, 'WR': 3, 'TE': 1, 'DST': 1, 'FLEX': 1},
        position_column='pos',
        flex_positions=('RB', 'WR', 'TE')
    )

Using with GeneticAlgorithm

from stevedore.named import NamedExtensionManager

# Set up validation extension manager
emgrs = {
    'validate': NamedExtensionManager(
        namespace='pangadfs.validate',
        names=['validate_salary', 'validate_duplicates', 'validate_positions'],
        invoke_on_load=True,
        name_order=True
    )
}

ga = GeneticAlgorithm(ctx=ctx, extension_managers=emgrs)

Module Consolidation

Note: All validation classes are now consolidated in the single pangadfs.validate module. Previously, position validation classes were in a separate validate_positions module, but they have been moved for better organization and easier imports.

Migration: If you were previously importing from pangadfs.validate_positions, simply change your imports to use pangadfs.validate:

# Old (no longer works)
from pangadfs.validate_positions import PositionValidate

# New (current)
from pangadfs.validate import PositionValidate

API Reference

pangadfs.validate

FlexDuplicatesValidate()

Bases: ValidateBase

Validates that FLEX positions don't duplicate other positions. This replaces the expensive duplicate checking that was in PopulateDefault. Uses a more efficient vectorized approach.

Source code in pangadfs/base.py
def __init__(self):
    logging.getLogger(__name__).addHandler(logging.NullHandler())

PositionValidate()

Bases: ValidateBase

Validates that lineups meet position requirements

Source code in pangadfs/base.py
def __init__(self):
    logging.getLogger(__name__).addHandler(logging.NullHandler())

validate(*, population, pool, posmap, position_column='pos', flex_positions=('RB', 'WR', 'TE'), **kwargs)

Validates that each lineup meets position requirements

Parameters:

Name Type Description Default
population ndarray

Array of lineups (population_size, lineup_size)

required
pool DataFrame

Player pool DataFrame with position information

required
posmap Dict[str, int]

Position requirements (e.g., {'QB': 1, 'RB': 2, 'WR': 3, 'TE': 1, 'DST': 1, 'FLEX': 1})

required
position_column str

Column name for positions in pool

'pos'
flex_positions tuple

Positions that can fill FLEX slots

('RB', 'WR', 'TE')

Returns:

Type Description
ndarray

np.ndarray: Filtered population with only valid lineups

Source code in pangadfs/validate.py
def validate(self, *, 
             population: np.ndarray,
             pool: pd.DataFrame,
             posmap: Dict[str, int],
             position_column: str = 'pos',
             flex_positions: tuple = ('RB', 'WR', 'TE'),
             **kwargs) -> np.ndarray:
    """
    Validates that each lineup meets position requirements

    Args:
        population: Array of lineups (population_size, lineup_size)
        pool: Player pool DataFrame with position information
        posmap: Position requirements (e.g., {'QB': 1, 'RB': 2, 'WR': 3, 'TE': 1, 'DST': 1, 'FLEX': 1})
        position_column: Column name for positions in pool
        flex_positions: Positions that can fill FLEX slots

    Returns:
        np.ndarray: Filtered population with only valid lineups
    """
    if len(population) == 0:
        return population

    # Get position information for all players
    player_positions = pool[position_column].to_dict()

    valid_lineups = []

    for lineup in population:
        if self._is_lineup_valid(lineup, player_positions, posmap, flex_positions):
            valid_lineups.append(lineup)

    if len(valid_lineups) == 0:
        # If no valid lineups, return empty array with correct shape
        return np.empty((0, population.shape[1]), dtype=population.dtype)

    return np.array(valid_lineups)

PositionValidateOptimized()

Bases: ValidateBase

Optimized version using vectorized operations where possible

Source code in pangadfs/base.py
def __init__(self):
    logging.getLogger(__name__).addHandler(logging.NullHandler())

validate(*, population, pool, posmap, position_column='pos', flex_positions=('RB', 'WR', 'TE'), **kwargs)

Validates that each lineup meets position requirements using optimized approach

Source code in pangadfs/validate.py
def validate(self, *, 
             population: np.ndarray,
             pool: pd.DataFrame,
             posmap: Dict[str, int],
             position_column: str = 'pos',
             flex_positions: tuple = ('RB', 'WR', 'TE'),
             **kwargs) -> np.ndarray:
    """
    Validates that each lineup meets position requirements using optimized approach
    """
    if len(population) == 0:
        return population

    # Create position mapping array for fast lookup
    max_player_id = max(pool.index.max(), population.max()) + 1
    position_array = np.full(max_player_id, '', dtype='U5')

    for player_id, pos in zip(pool.index, pool[position_column]):
        position_array[player_id] = pos

    # Vectorized validation
    valid_mask = np.array([
        self._is_lineup_valid_vectorized(lineup, position_array, posmap, flex_positions)
        for lineup in population
    ])

    return population[valid_mask]

SalaryValidate()

Bases: ValidateBase

Source code in pangadfs/base.py
def __init__(self):
    logging.getLogger(__name__).addHandler(logging.NullHandler())

validate(*, population, salaries, salary_cap, **kwargs)

Ensures valid individuals in population

Parameters:

Name Type Description Default
population ndarray

the population to validate

required
salaries ndarray

1D where indices are in same order as player indices

required
salary_cap int

the salary cap, e.g., 50000 or 60000

required
**kwargs

keyword arguments for plugins

{}

Returns:

Type Description
ndarray

np.ndarray: same width as population, likely has less rows

Source code in pangadfs/validate.py
def validate(self,
             *, 
             population: np.ndarray,
             salaries: np.ndarray,
             salary_cap: int, 
             **kwargs) -> np.ndarray:
    """Ensures valid individuals in population

        Args:
            population (np.ndarray): the population to validate
            salaries (np.ndarray): 1D where indices are in same order as player indices
            salary_cap (int): the salary cap, e.g., 50000 or 60000
            **kwargs: keyword arguments for plugins

        Returns:
            np.ndarray: same width as population, likely has less rows

    """
    if len(population) == 0:
        return population

    # Use take for potentially faster indexing
    salary_matrix = np.take(salaries, population)
    popsal = np.sum(salary_matrix, axis=1)

    # Use nonzero for potentially faster boolean indexing
    valid_indices = np.nonzero(popsal <= salary_cap)[0]
    return population[valid_indices]