<commit_before>import pulp
import numpy as np
import conference_scheduler.lp_problem as lp
from conference_scheduler.resources import ScheduledItem, Shape


def all_constraints(events, slots, X, constraints=None):
    """Compute a list of generator functions which will each produce a list
    of constraints

    Parameters
    ----------
        events : list or tuple
            of resources.Event instances
        slots : list or tuple
            of resources.Slot instances
        X : dict or np.array
            mapping a tuple of event index and slot index to a condition
            statement
        constraints: list or tuple
            of generator functions which each produce instances of
            resources.Constraint

    Returns
    -------
        list
            of generator functions each of which produces a further list of
            instances of resource.Constraint
    """
    generators = [lp.constraints.all_constraints(events, slots, X)]
    if constraints is not None:
        generators.append(constraints)
    for generator in generators:
        for constraint in generator:
            yield constraint


# Three functions that can be called by external programs to produce the
# schedule in one of three forms:
#   solution: a generator for a list of tuples of event index and slot index
#             for each scheduled item
#   array: a numpy array with rows for events and columns for slots
#   schedule: a generator for a list of ScheduledItem instances


def solution(events, slots, constraints=None, objective_function=None):
    """Setup up the ILP problem, submit it to pulp and return the solution

    Parameters
    ----------
        events : list or tuple
            of resources.Event instances
        slots : list or tuple
            of resources.Slot instances
        constraints : list or tuple
            of generator functions which each produce instances of
            resources.Constraint
        objective_function: callable
            from lp_problem.objective_functions

    Returns
    -------
        Generator
            of tuples giving the event and slot index (for the given events and
            slots lists) for all scheduled items.

            e.g. for a solution where:
                event 0 is scheduled in slot 1
                event 1 is scheduled in slot 4
                event 2 is scheduled in slot 5

            the resulting generator would produce:
                [(0, 1), (1, 4), (2, 5)]
    """
    shape = Shape(len(events), len(slots))
    problem = pulp.LpProblem()
    X = lp.utils.variables(shape)

    for constraint in all_constraints(events, slots, X, constraints):
        problem += constraint.condition

    if objective_function is not None:
        problem += objective_function(events=events, slots=slots, X=X)

    status = problem.solve()
    if status == 1:
        return (
            item for item, variable in X.items()
            if variable.value() > 0
        )
    else:
        raise ValueError('No valid solution found')


def array(events, slots, constraints=None, objective_function=None):
    """Compute the ILP solution and return it in array form

     Parameters
    ----------
        events : list or tuple
            of resources.Event instances
        slots : list or tuple
            of resources.Slot instances
        constraints : list or tuple
            of generator functions which each produce instances of
            resources.Constraint
        objective_function : callable
            from lp_problem.objective_functions

    Returns
    -------
        np.array
            an E by S array (X) where E is the number of events and S the
            number of slots.
            Xij is 1 if event i is scheduled in slot j and zero otherwise

            e.g. 3 events, 7 slots and a solution where:
                event 0 is scheduled in slot 1
                event 1 is scheduled in slot 4
                event 2 is scheduled in slot 5

            the resulting array would be:
                [[0, 1, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 1, 0, 0],
                 [0, 0, 0, 0, 0, 1, 0]]
    """
    array = np.zeros((len(events), len(slots)))
    for item in solution(events, slots, constraints, objective_function):
        array[item[0], item[1]] = 1
    return array


def schedule(events, slots, constraints=None, objective_function=None):
    """Compute the ILP solution and return it in schedule form

     Parameters
    ----------
        events : list or tuple
            of resources.Event instances
        slots : list or tuple
            of resources.Slot instances
        constraints : list or tuple
            of generator functions which each produce instances of
            resources.Constraint
        objective_function : callable
            from lp_problem.objective_functions

    Returns
    -------
        Generator
            of tuples of instances of resources.ScheduledItem
    """
    return (
        ScheduledItem(
            event=events[item[0]],
            slot=slots[item[1]]
        )
        for item in solution(
            events, slots, constraints, objective_function
        )
    )


# Functions to convert the schedule from one form to another


def schedule_to_array(schedule, events, slots):
    array = np.zeros((len(events), len(slots)))
    for item in schedule:<commit_msg>[#23] Add function to convert solution to array form<commit_after>import pulp
import numpy as np
import conference_scheduler.lp_problem as lp
from conference_scheduler.resources import ScheduledItem, Shape


def all_constraints(events, slots, X, constraints=None):
    """Compute a list of generator functions which will each produce a list
    of constraints

    Parameters
    ----------
        events : list or tuple
            of resources.Event instances
        slots : list or tuple
            of resources.Slot instances
        X : dict or np.array
            mapping a tuple of event index and slot index to a condition
            statement
        constraints: list or tuple
            of generator functions which each produce instances of
            resources.Constraint

    Returns
    -------
        list
            of generator functions each of which produces a further list of
            instances of resource.Constraint
    """
    generators = [lp.constraints.all_constraints(events, slots, X)]
    if constraints is not None:
        generators.append(constraints)
    for generator in generators:
        for constraint in generator:
            yield constraint


# Three functions that can be called by external programs to produce the
# schedule in one of three forms:
#   solution: a generator for a list of tuples of event index and slot index
#             for each scheduled item
#   array: a numpy array with rows for events and columns for slots
#   schedule: a generator for a list of ScheduledItem instances


def solution(events, slots, constraints=None, objective_function=None):
    """Setup up the ILP problem, submit it to pulp and return the solution

    Parameters
    ----------
        events : list or tuple
            of resources.Event instances
        slots : list or tuple
            of resources.Slot instances
        constraints : list or tuple
            of generator functions which each produce instances of
            resources.Constraint
        objective_function: callable
            from lp_problem.objective_functions

    Returns
    -------
        Generator
            of tuples giving the event and slot index (for the given events and
            slots lists) for all scheduled items.

            e.g. for a solution where:
                event 0 is scheduled in slot 1
                event 1 is scheduled in slot 4
                event 2 is scheduled in slot 5

            the resulting generator would produce:
                [(0, 1), (1, 4), (2, 5)]
    """
    shape = Shape(len(events), len(slots))
    problem = pulp.LpProblem()
    X = lp.utils.variables(shape)

    for constraint in all_constraints(events, slots, X, constraints):
        problem += constraint.condition

    if objective_function is not None:
        problem += objective_function(events=events, slots=slots, X=X)

    status = problem.solve()
    if status == 1:
        return (
            item for item, variable in X.items()
            if variable.value() > 0
        )
    else:
        raise ValueError('No valid solution found')


def array(events, slots, constraints=None, objective_function=None):
    """Compute the ILP solution and return it in array form

     Parameters
    ----------
        events : list or tuple
            of resources.Event instances
        slots : list or tuple
            of resources.Slot instances
        constraints : list or tuple
            of generator functions which each produce instances of
            resources.Constraint
        objective_function : callable
            from lp_problem.objective_functions

    Returns
    -------
        np.array
            an E by S array (X) where E is the number of events and S the
            number of slots.
            Xij is 1 if event i is scheduled in slot j and zero otherwise

            e.g. 3 events, 7 slots and a solution where:
                event 0 is scheduled in slot 1
                event 1 is scheduled in slot 4
                event 2 is scheduled in slot 5

            the resulting array would be:
                [[0, 1, 0, 0, 0, 0, 0],
                 [0, 0, 0, 0, 1, 0, 0],
                 [0, 0, 0, 0, 0, 1, 0]]
    """
    # array = np.zeros((len(events), len(slots)))
    # for item in solution(events, slots, constraints, objective_function):
    #     array[item[0], item[1]] = 1
    return solution_to_array(
        solution(events, slots, constraints, objective_function),
        events, slots)


def schedule(events, slots, constraints=None, objective_function=None):
    """Compute the ILP solution and return it in schedule form

     Parameters
    ----------
        events : list or tuple
            of resources.Event instances
        slots : list or tuple
            of resources.Slot instances
        constraints : list or tuple
            of generator functions which each produce instances of
            resources.Constraint
        objective_function : callable
            from lp_problem.objective_functions

    Returns
    -------
        Generator
            of tuples of instances of resources.ScheduledItem
    """
    return (
        ScheduledItem(
            event=events[item[0]],
            slot=slots[item[1]]
        )
        for item in solution(
            events, slots, constraints, objective_function
        )
    )


# Functions to convert the schedule from one form to another

def solution_to_array(solution, events, slots):
    array = np.zeros((len(events), len(slots)))
    for item in solution:
        array[item[0], item[1]] = 1
    return array


def schedule_to_array(schedule, events, slots):
    array = np.zeros((len(events), len(slots)))
    for item in schedule:
{'fraction_non_alphanumeric': 0.0694980694980695, 'fraction_numerical': 0.009248451108916225, 'mean_word_length': 1.9812633832976445, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2470102', 'n_tokens_mistral': 2790, 'n_tokens_neox': 2651, 'n_words': 1163}