OptaPy is an AI constraint solver for Python to optimize planning and scheduling problems.

Overview

OptaPy

PyPI Binder

OptaPy is an AI constraint solver for Python to optimize the Vehicle Routing Problem, Employee Rostering, Maintenance Scheduling, Task Assignment, School Timetabling, Cloud Optimization, Conference Scheduling, Job Shop Scheduling, Bin Packing and many more planning problems.

OptaPy wraps the OptaPlanner engine internally, but using OptaPy in Python is significantly slower than using OptaPlanner in Java or Kotlin.

Warning
OptaPy is an experimental technology. It is at least 20 times slower than using OptaPlanner in Java or Kotlin.

Get started

Prerequisites

  1. Install Python 3.9 or later.

  2. Install JDK 11 or later with the environment variable JAVA_HOME configured to the JDK installation directory.

Installing

pip install optapy

Source code overview

Domain

In OptaPy, the domain has three parts:

  • Problem Facts, which do not change

  • Planning Entities, which have one or more planning variables

  • Planning Solution, which define the facts and entities of the problem

Problem Facts

To declare Problem Facts, use the @problem_fact decorator

from optapy import problem_fact

@problem_fact
class Timeslot:
    def __init__(self, id, day_of_week, start_time, end_time):
        self.id = id
        self.day_of_week = day_of_week
        self.start_time = start_time
        self.end_time = end_time

Planning Entities

To declare Planning Entities, use the @planning_entity decorator

from optapy import planning_entity, planning_id, planning_variable

@planning_entity
class Lesson:
    def __init__(self, id, subject, teacher, student_group, timeslot=None, room=None):
        self.id = id
        self.subject = subject
        self.teacher = teacher
        self.student_group = student_group
        self.timeslot = timeslot
        self.room = room

    @planning_id
    def get_id(self):
        return self.id

    @planning_variable(Timeslot, value_range_provider_refs=["timeslotRange"])
    def get_timeslot(self):
        return self.timeslot

    def set_timeslot(self, new_timeslot):
        self.timeslot = new_timeslot

    @planning_variable(Room, value_range_provider_refs=["roomRange"])
    def get_room(self):
        return self.room

    def set_room(self, new_room):
        self.room = newRoom
  • @planning_variable method decorators are used to indicate what fields can change. The method MUST begin with get and have a corresponding set method (i.e. get_room(self), set_room(self, newRoom)). The first parameter of the decorator is the type of the Planning Variable (required). The value_range_provider_refs parameter tells OptaPlanner what value range providers on the Planning Solution this Planning Variable can take values from.

  • @planning_id is used to uniquely identify an entity object of a particular class. The same Planning Id can be used on entities of different classes, but the ids of all entities in the same class must be different.

Planning Solution

To declare the Planning Solution, use the @planning_solution decorator

from optapy import planning_solution, problem_fact_collection_property, value_range_provider, planning_entity_collection_property, planning_score

@planning_solution
class TimeTable:
    def __init__(self, timeslot_list, room_list, lesson_list, score=None):
        self.timeslot_list = timeslot_list
        self.room_list = room_list
        self.lesson_list = lesson_list
        self.score = score

    @problem_fact_collection_property(Timeslot)
    @value_range_provider(range_id = "timeslotRange")
    def get_timeslot_list(self):
        return self.timeslot_list

    @problem_fact_collection_property(Room)
    @value_range_provider(range_id = "roomRange")
    def get_room_list(self):
        return self.room_list

    @planning_entity_collection_property(Lesson)
    def get_lesson_list(self):
        return self.lesson_list

    @planning_score(HardSoftScore)
    def get_score(self):
        return self.score

    def set_score(self, score):
        self.score = score
  • @value_range_provider(range_id) is used to indicate a method returns values a Planning Variable can take. It can be referenced by its id in the value_range_provider_refs parameter of @planning_variable. It should also have a @problem_fact_collection_property or a @planning_entity_collection_property.

  • @problem_fact_collection_property(type) is used to indicate a method returns Problem Facts. The first parameter of the decorator is the type of the Problem Fact Collection (required). It should be a list.

  • @planning_entity_collection_property(type) is used to indicate a method returns Planning Entities. The first parameter of the decorator is the type of the Planning Entity Collection (required). It should be a list.

  • @planning_score(scoreType) is used to tell OptaPlanner what field holds the score. The method MUST begin with get and have a corresponding set method (i.e. get_score(self), set_score(self, score)). The first parameter of the decorator is the score type (required).

Constraints

You define your constraints by using the ConstraintFactory

from domain import Lesson
from optapy import get_class, constraint_provider
from optapy.types import Joiners, HardSoftScore

# Get the Java class corresponding to the Lesson Python class
LessonClass = get_class(Lesson)

@constraint_provider
def define_constraints(constraint_factory):
    return [
        # Hard constraints
        room_conflict(constraint_factory),
        # Other constraints here...
    ]

def room_conflict(constraint_factory):
    # A room can accommodate at most one lesson at the same time.
    return constraint_factory \
            .fromUniquePair(LessonClass, [
            # ... in the same timeslot ...
                Joiners.equal(lambda lesson: lesson.timeslot),
            # ... in the same room ...
                Joiners.equal(lambda lesson: lesson.room)]) \
            .penalize("Room conflict", HardSoftScore.ONE_HARD)
Note
Since from is a keyword in python, to use the constraint_factory.from(class, [joiners…​]) function, you access it like constraint_factory.from_(class, [joiners…​])

Solve

from optapy import get_class, solve
from optapy.types import SolverConfig, Duration
from constraints import define_constraints
from domain import TimeTable, Lesson, generate_problem

solver_config = SolverConfig().withEntityClasses(get_class(Lesson)) \
    .withSolutionClass(get_class(TimeTable)) \
    .withConstraintProviderClass(get_class(define_constraints)) \
    .withTerminationSpentLimit(Duration.ofSeconds(30))

solution = solve(solver_config, generate_problem())

solution will be a TimeTable instance with planning variables set to the final best solution found.

Build

  1. Install the python build module (if not already installed):

    pip install build
  2. In the optapy-core directory, use the command below to build the optapy python wheel into the dist directory:

    cd optapy-core
    python -m build
  3. Install it into a virtual environment using pip:

    # Activate a virtual environment first
    source my_project/venv/bin/activate
    pip install dist/optapy-*-py3-none-any.whl

Run

Running run.sh runs optapy-quickstarts/school-timetabling/main.py after building optapy and installing it to optapy-quickstarts/school-timetabling/venv.

More information

For a complete example, see the school timetabling quickstart. For a full API spec, visit OptaPlanner Documentation.

Comments
  • Add JPype support

    Add JPype support

    This PR adds JPype support, which allows it to be used with regular Python. It is approximately 3 times slower than the GraalVM version, which is 10 time slower than Java.

    opened by Christopher-Chianelli 12
  • TypeError: Ambiguous overloads ... when using ConstraintCollectors.compose

    TypeError: Ambiguous overloads ... when using ConstraintCollectors.compose

    I am currently trying to optimize some shifts. As these shifts start every 8 hours I want to make sure that no person does more than 2 shifts in a row and has to work 24h at once.

    My idea was to group all shift assignments by person and then use a composed collector to get the earliest and latest shift and then make sure these shifts do not fill the entire 24 hours (because another constraint is that every person gets exactly 3 shifts).

    ONE_DAY_IN_SECONDS = 24 * 60 * 60
    def diff_in_seconds(earliest, latest):
        # I tried timedelta before but that did not work either
        return (latest - earliest).total_seconds()
    
    def no_24h_marathon(constraint_factory):
        return constraint_factory.forEach(assignment_class).groupBy(
            lambda a: a.person.name,
            ConstraintCollectors.compose(
                ConstraintCollectors.min(lambda a: a.shift.start),
                ConstraintCollectors.max(lambda a: a.shift.end),
                more_than_16h,
            )
        ).penalize("No 24h marathon", HardSoftScore.ONE_HARD, lambda _, c: c > ONE_DAY_IN_SECONDS )
    

    When I do this I get this TypError about overloads when trying to solve:

    TypeError: Ambiguous overloads found for org.optaplanner.core.api.score.stream.ConstraintCollectors.min(function) between:
    	public static org.optaplanner.core.api.score.stream.uni.UniConstraintCollector org.optaplanner.core.api.score.stream.ConstraintCollectors.min(java.util.function.Function)
    	public static org.optaplanner.core.api.score.stream.tri.TriConstraintCollector org.optaplanner.core.api.score.stream.ConstraintCollectors.min(org.optaplanner.core.api.function.TriFunction)
    	public static org.optaplanner.core.api.score.stream.quad.QuadConstraintCollector org.optaplanner.core.api.score.stream.ConstraintCollectors.min(org.optaplanner.core.api.function.QuadFunction)
    	public static org.optaplanner.core.api.score.stream.bi.BiConstraintCollector org.optaplanner.core.api.score.stream.ConstraintCollectors.min(java.util.function.BiFunction)
    

    Should I use a different approach? Any and every help would be greatly appreciated. Thanks for this python wrapper, it helps a lot!

    opened by MrGreenTea 8
  • Return value is not compatible with required type

    Return value is not compatible with required type

    Hi, I am getting the Return value is not compatible with required type error - how can I tell the types involved (expected and actual), so I can solve this error?

    By the way, is the NotADirectoryError and PermissionError errors following the TypeError in the end 'real', or are theycaused by the type mismatch?

    Thanks

    C:\Users\User\Project\venv\Scripts\python.exe C:/Users/User/Project/optapy1.py
    11:11:20,084 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
    11:11:20,084 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
    11:11:20,084 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [jar:file:/C:/Users/User/AppData/Local/Temp/tmpy3fynomc/optapy-8.11.0.Final-sources.jar!/logback.xml]
    11:11:20,084 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs multiple times on the classpath.
    11:11:20,084 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [jar:file:/C:/Users/User/AppData/Local/Temp/tmpy3fynomc/optapy-8.11.0.Final-sources.jar!/logback.xml]
    11:11:20,084 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [jar:file:/C:/Users/User/AppData/Local/Temp/tmpy3fynomc/optapy-8.11.0.Final.jar!/logback.xml]
    11:11:20,091 |-INFO in ch.qos.logback.core.joran.spi.ConfigurationWatchList@4f0f2942 - URL [jar:file:/C:/Users/User/AppData/Local/Temp/tmpy3fynomc/optapy-8.11.0.Final-sources.jar!/logback.xml] is not of type file
    11:11:20,152 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
    11:11:20,152 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
    11:11:20,156 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [consoleAppender]
    11:11:20,159 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
    11:11:20,204 |-INFO in ch.qos.logback.classic.joran.action.LoggerAction - Setting level of logger [org.optaplanner] to INFO
    11:11:20,204 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to WARN
    11:11:20,204 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [consoleAppender] to Logger[ROOT]
    11:11:20,205 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
    11:11:20,207 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@2657d4dd - Registering current configuration as safe fallback point
    
    Traceback (most recent call last):
      File "C:\Users\User\Project\optapy1.py", line 129, in <module>
        solution = solve(solverConfig, generateProblem())
      File "C:\Users\User\Project\venv\lib\site-packages\optapy\optaplanner_java_interop.py", line 299, in solve
        solution = _unwrap_java_object(PythonSolver.solve(solver_config,
    TypeError: Return value is not compatible with required type.
    
    Traceback (most recent call last):
      File "C:\Program Files\Python39\lib\shutil.py", line 616, in _rmtree_unsafe
        os.unlink(fullname)
    PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\User\\AppData\\Local\\Temp\\tmpy3fynomc\\antlr-runtime-3.5.2.jar'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "C:\Program Files\Python39\lib\tempfile.py", line 801, in onerror
        _os.unlink(path)
    PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\User\\AppData\\Local\\Temp\\tmpy3fynomc\\antlr-runtime-3.5.2.jar'
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "C:\Program Files\Python39\lib\weakref.py", line 656, in _exitfunc
        f()
      File "C:\Program Files\Python39\lib\weakref.py", line 580, in __call__
        return info.func(*info.args, **(info.kwargs or {}))
      File "C:\Program Files\Python39\lib\tempfile.py", line 816, in _cleanup
        cls._rmtree(name)
      File "C:\Program Files\Python39\lib\tempfile.py", line 812, in _rmtree
        _shutil.rmtree(name, onerror=onerror)
      File "C:\Program Files\Python39\lib\shutil.py", line 740, in rmtree
        return _rmtree_unsafe(path, onerror)
      File "C:\Program Files\Python39\lib\shutil.py", line 618, in _rmtree_unsafe
        onerror(os.unlink, fullname, sys.exc_info())
      File "C:\Program Files\Python39\lib\tempfile.py", line 804, in onerror
        cls._rmtree(path)
      File "C:\Program Files\Python39\lib\tempfile.py", line 812, in _rmtree
        _shutil.rmtree(name, onerror=onerror)
      File "C:\Program Files\Python39\lib\shutil.py", line 740, in rmtree
        return _rmtree_unsafe(path, onerror)
      File "C:\Program Files\Python39\lib\shutil.py", line 599, in _rmtree_unsafe
        onerror(os.scandir, path, sys.exc_info())
      File "C:\Program Files\Python39\lib\shutil.py", line 596, in _rmtree_unsafe
        with os.scandir(path) as scandir_it:
    NotADirectoryError: [WinError 267] The directory name is invalid: 'C:\\Users\\User\\AppData\\Local\\Temp\\tmpy3fynomc\\antlr-runtime-3.5.2.jar'
    
    Process finished with exit code 1
    
    opened by ScDor 7
  • Add workflow to run SonarCloud on main

    Add workflow to run SonarCloud on main

    The majority of testing is done on in Python tests; the Java tests mostly act as a sanity check, since in order to actually test all the parts, we need to test in Python (otherwise, we are just testing how we think it works, not how it actually works).

    In order to let Python tests contribute to the test coverage, the action downloads the JaCoCo runtime agent, and add it as an argument when the test JVM starts.

    Closes #116

    opened by Christopher-Chianelli 6
  • Fix issues in Sonarcloud action

    Fix issues in Sonarcloud action

    • setup-python fails if it cannot find a requirements.txt file if cache-dependency-path is not set
    • For some reason, Java 11 JVM crash with Python JaCoCo execution, but Java 17 JVM does not
    opened by Christopher-Chianelli 5
  • Launch two solver in a row make the second one crash

    Launch two solver in a row make the second one crash

    Hello, I have a problem that I split into two parts. When I run a first solver with the first part, then at the end a second solver with the second part. The second one crashes systematically with the error : java.lang.RuntimeException: java.lang.IllegalArgumentException: OptaPySolver does not exist in global scope The strangest thing is that if I change the order of my problems it is always the one I put first that works. As if running the solver twice would cause it to crash. Is this a known bug ?

    opened by adrdv 3
  • Support for

    Support for "dropped nodes"?

    Hello,

    I am currently testing a situation where most of the customer's demands are higher than any vehicle capacity (using the default constraints provided by the vehicle routing example)

    The results are interesting since it show that most vehicles are allocated "over capacity" - is this expected behavior?

    Thanks!

    opened by bilics 3
  • [bot]: Bump optaplanner-build-parent from 8.30.0.Final to 8.31.1.Final

    [bot]: Bump optaplanner-build-parent from 8.30.0.Final to 8.31.1.Final

    Bumps optaplanner-build-parent from 8.30.0.Final to 8.31.1.Final.

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies java 
    opened by dependabot[bot] 2
  • [bot]: Bump version.org.ow2.asm from 9.3 to 9.4

    [bot]: Bump version.org.ow2.asm from 9.3 to 9.4

    Bumps version.org.ow2.asm from 9.3 to 9.4. Updates asm-util from 9.3 to 9.4

    Updates asm-tree from 9.3 to 9.4

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies java 
    opened by dependabot[bot] 2
  • [bot]: Bump gizmo from 1.0.11.Final to 1.4.0.Final

    [bot]: Bump gizmo from 1.0.11.Final to 1.4.0.Final

    Bumps gizmo from 1.0.11.Final to 1.4.0.Final.

    Commits
    • 33e0179 [maven-release-plugin] prepare release 1.4.0.Final
    • 9c1c4b3 Merge pull request #131 from Ladicek/bitwise-operations
    • c5b8084 Merge pull request #129 from oliv37/patch-1
    • a9869fa Merge pull request #130 from oliv37/patch-2
    • af71b0c Small change to how float and double fields are compared in generated `eq...
    • d242b19 Add methods for emitting bitwise AND, OR, XOR
    • 25e1f1f Merge pull request #128 from Ladicek/improvements
    • 500be52 Add documentation of high-level utilities and improve consistency
    • d82fdb9 Add high-level utilities for generating equals, hashCode and toString m...
    • 05307df Add a high-level utility for generating StringBuilder chains
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies java 
    opened by dependabot[bot] 2
  • Integration with GraphHopper (or other routing service)

    Integration with GraphHopper (or other routing service)

    Hi,

    Is it just a matter of replacing the distance calculator with such service?

    And the "final result" would then contain the comprehensive list of lat/lng with the complete routing?

    Thanks for any pointers!

    opened by bilics 2
  • [bot]: Bump gizmo from 1.4.0.Final to 1.5.0.Final

    [bot]: Bump gizmo from 1.4.0.Final to 1.5.0.Final

    Bumps gizmo from 1.4.0.Final to 1.5.0.Final.

    Commits
    • f1d615d [maven-release-plugin] prepare release 1.5.0.Final
    • 0c37c22 Merge pull request #142 from quarkusio/dependabot/maven/io.smallrye-jandex-3.0.5
    • ab1c927 Merge pull request #146 from mkouba/string-switch-optimize-hash-collision
    • f51bebd StringSwitch - fix hashCode collisons
    • 1185f56 Merge pull request #144 from mkouba/fix-switch-enclosing-scope
    • 3ff5a0f Merge pull request #145 from mkouba/fix-classcreator-constructor
    • 9a26ffa Fix backward compatibility issue with public constructor of ClassCreator
    • 4cb5358 String/Enum switch - make result handles from enclosing scope accesible
    • 4386adf Merge pull request #143 from mkouba/string-switch
    • 9a9e73e Add Switch constructs for String and Enum
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies java 
    opened by dependabot[bot] 0
  • jpyinterpreter - float, int str constructor support

    jpyinterpreter - float, int str constructor support

    Python float and int accept str as constructor arguments, so jpyinterpreter should too.

    Expected behaviour:

    a = float('inf')
    b  = float('1.0')
    assert a == infinity
    assert b == 1.0
    
    opened by Christopher-Chianelli 0
  • jpyinterpreter - Keep module attributes' type infomation

    jpyinterpreter - Keep module attributes' type infomation

    When a module is loaded via LOAD_MODULE, jpyinterpreter currently does not have access to the type of attributes in the modules. This result in losing type infomation when a Type is loaded from a module, generating less efficient Java bytecode.

    enhancement 
    opened by Christopher-Chianelli 0
  • jpyinterpreter - make FOR_ITER use Java iterator loop format when possible

    jpyinterpreter - make FOR_ITER use Java iterator loop format when possible

    Currently, in order to fully support all the forms a Python iterator can take, jpyinterpreter generates the following code for FOR_ITER:

    try {
        do {
            TOS' = next(TOS)
             // code in for block
        } while(true);
    } catch (StopIteration e) {
        // code after for block
    }
    

    This is highly atypical in Java, and the JVM probably would have a harder time optimizing its standard for iterator loop:

    while (TOS.hasNext()) {
        TOS' = TOS.next();
        // code in for block
    }
     // code after for block
    

    We can look at TOS to see if it a known iterator type (i.e. PythonIterator), and if so, generate the more typical Java loop.

    enhancement 
    opened by Christopher-Chianelli 0
  • jpyinterpreter - Support match statements

    jpyinterpreter - Support match statements

    See https://peps.python.org/pep-0634/

    This require the following opcodes:

    • COPY_DICT_WITHOUT_KEYS
    • GET_LEN
    • MATCH_MAPPING
    • MATCH_SEQUENCE
    • MATCH_KEYS
    • MATCH_CLASS(count)
    enhancement 
    opened by Christopher-Chianelli 1
Releases(8.31.1b0)
  • 8.31.1b0(Dec 12, 2022)

    Add support for Python 3.11 for jpyinterpreter, significantly improving Python 3.11 score calculation speeds.

    Also optimize how calls are done in the interpreter, which can provide a modest improvement to score calculation speeds for some constraints.

    Source code(tar.gz)
    Source code(zip)
  • 8.30.0b0(Nov 22, 2022)

    Add the ConstraintVerifier API to allow testing of constraints. See https://www.optapy.org/docs/latest/constraint-streams/constraint-streams.html#constraintStreamsTesting for details.

    Source code(tar.gz)
    Source code(zip)
  • 8.28.0b0(Oct 27, 2022)

    This is the first release of optapy that includes jpyinterpreter, a module created to translate Python function bytecode to equivalent Java bytecode to massively increase performance by avoiding Foreign Function Interface (FFI) calls. You don't need to do anything in order to use it; it is on by default. Functions and classes that cannot be translated will be proxied to their CPython functions and types.

    Bug fixes:

    • Support ValueRange, CountableValueRange and entity @value_range_provider
    • Support arbitary PythonComparable as @planning_id
    Source code(tar.gz)
    Source code(zip)
  • 8.23.0a0(Jul 6, 2022)

    • Bug Fix: SolverManager solve and solveAndListen will now show exceptions
    • Bug Fix: A Uni, Bi, and Tri Constraint Stream can now join an UniConstraintStream
    Source code(tar.gz)
    Source code(zip)
  • 8.21.0a0(Jun 16, 2022)

    Dependency Upgrades:

    JPype1 upgraded to 1.4.0, which fixes ambiguity errors when dealing with overloaded methods

    New Features:

    • get_class is not longer required when interacting with SolverConfig and Constraint Streams
    • Pythonic version of Constraint Stream, Joiners, and ConstraintCollectors methods
    • New decorators @custom_shadow_variable and @variable_listener, which can be used to create a custom shadow variable that changes when a geninue @planning_variable (or another shadow variable) changes.
    Source code(tar.gz)
    Source code(zip)
  • 8.19.0a1(May 17, 2022)

    • Remove memory leak caused by old best solution being retained until solving finishes
    • Add support for tuple and set collections, and collections that extend the collection.abc abstract base classes
    • Allow group by keys to be interacted with like normal python objects
    Source code(tar.gz)
    Source code(zip)
  • 8.19.0a0(Mar 29, 2022)

    New Features:

    • Ability to load a SolverConfig via XML from solver_config_create_from_xml_file(pathlib.Path)
    • Can modify the log level of optapy at runtime with logging

    Fixed Bugs:

    • Logback configuration logs will no longer appear
    Source code(tar.gz)
    Source code(zip)
  • 8.17.0a0(Mar 8, 2022)

    • New decorator @planning_list_variable, which can be used to model variables as an ordered disjoint set (for example, the customers to visit in vehicle routing).
    • Support for @problem_change, which allows changing the problem during solving.
    • List available subpackages in optapy.config, validate collection decorators.
    Source code(tar.gz)
    Source code(zip)
  • 8.16.1a0(Feb 9, 2022)

    • Upgrade OptaPlanner version to 8.16.1.Final
    • Add @easy_score_calculator decorator
    • Add @incremental_score_calculator decorator
    • Fix bug in ScoreManager that causes an exception in concurrent requests in different threads
    • Add SolverStatus to optapy.types
    Source code(tar.gz)
    Source code(zip)
  • 8.14.0a0(Dec 17, 2021)

    New Features:

    • All Python Types are supported in Joiners/ConstraintCollectors/etc, so that TypeError now never happens. If you happen to return a bad type in a method that expects a particular type (ex: returning a str instead of a bool in a filter), a TypeError will be raised with some general helping info
    • The following API from OptaPlanner have been exposed: SolverFactory, SolverManager, ScoreManager (which can be accessed via solver_factory_create, solver_manager_create, score_manager_create).
    • The following annotations from OptaPlanner been exposed as annotations: @anchor_shadow_variable, @inverse_relation_shadow_variable, @planning_pin; pinning_filter is also now available as an optional value that can be defined on @planning_entity
    • SolverFactory is for blocking solving, SolverManager is for asynchronously solving, ScoreManager is to get the score and violated constraints without solving.
    • Type stubs have been added via stubgenj

    Deprecations:

    • from have been deprecated in OptaPlanner (from_ in OptaPy) due to its semantics changing depending on if over-constrained planning is used. Now use forEach/forEachIncludingNullVars instead, which has consistent semantics in both regular and over-constrained planning.

    Breaking Changes:

    • solve as a global function has been removed from OptaPy as there is no equivalent static method in OptaPlanner yet. Replace solve(solver_config, problem) with solver_factory_create(solver_config).buildSolver().solve(problem).
    Source code(tar.gz)
    Source code(zip)
  • 8.11.0a2(Oct 7, 2021)

  • 8.11.0a1(Sep 16, 2021)

  • 8.11.0a0(Sep 16, 2021)

Owner
OptaPy
Python module for OptaPlanner (Alpha)
OptaPy
Pyomo is an object-oriented algebraic modeling language in Python for structured optimization problems.

Pyomo is a Python-based open-source software package that supports a diverse set of optimization capabilities for formulating and analyzing optimization models. Pyomo can be used to define symbolic problems, create concrete problem instances, and solve these instances with standard solvers.

Pyomo 1.4k Dec 28, 2022
A linear equation solver using gaussian elimination. Implemented for fun and learning/teaching.

A linear equation solver using gaussian elimination. Implemented for fun and learning/teaching. The solver will solve equations of the type: A can be

Sanjeet N. Dasharath 3 Feb 15, 2022
High performance, easy-to-use, and scalable machine learning (ML) package, including linear model (LR), factorization machines (FM), and field-aware factorization machines (FFM) for Python and CLI interface.

What is xLearn? xLearn is a high performance, easy-to-use, and scalable machine learning package that contains linear model (LR), factorization machin

Chao Ma 3k Jan 8, 2023
Scalable, Portable and Distributed Gradient Boosting (GBDT, GBRT or GBM) Library, for Python, R, Java, Scala, C++ and more. Runs on single machine, Hadoop, Spark, Dask, Flink and DataFlow

eXtreme Gradient Boosting Community | Documentation | Resources | Contributors | Release Notes XGBoost is an optimized distributed gradient boosting l

Distributed (Deep) Machine Learning Community 23.6k Jan 3, 2023
Uber Open Source 1.6k Dec 31, 2022
learn python in 100 days, a simple step could be follow from beginner to master of every aspect of python programming and project also include side project which you can use as demo project for your personal portfolio

learn python in 100 days, a simple step could be follow from beginner to master of every aspect of python programming and project also include side project which you can use as demo project for your personal portfolio

BDFD 6 Nov 5, 2022
A library of extension and helper modules for Python's data analysis and machine learning libraries.

Mlxtend (machine learning extensions) is a Python library of useful tools for the day-to-day data science tasks. Sebastian Raschka 2014-2021 Links Doc

Sebastian Raschka 4.2k Dec 29, 2022
A fast, scalable, high performance Gradient Boosting on Decision Trees library, used for ranking, classification, regression and other machine learning tasks for Python, R, Java, C++. Supports computation on CPU and GPU.

Website | Documentation | Tutorials | Installation | Release Notes CatBoost is a machine learning method based on gradient boosting over decision tree

CatBoost 6.9k Jan 5, 2023
Simple, fast, and parallelized symbolic regression in Python/Julia via regularized evolution and simulated annealing

Parallelized symbolic regression built on Julia, and interfaced by Python. Uses regularized evolution, simulated annealing, and gradient-free optimization.

Miles Cranmer 924 Jan 3, 2023
CyLP is a Python interface to COIN-OR’s Linear and mixed-integer program solvers (CLP, CBC, and CGL)

CyLP CyLP is a Python interface to COIN-OR’s Linear and mixed-integer program solvers (CLP, CBC, and CGL). CyLP’s unique feature is that you can use i

COIN-OR Foundation 161 Dec 14, 2022
To design and implement the Identification of Iris Flower species using machine learning using Python and the tool Scikit-Learn.

To design and implement the Identification of Iris Flower species using machine learning using Python and the tool Scikit-Learn.

Astitva Veer Garg 1 Jan 11, 2022
Python library which makes it possible to dynamically mask/anonymize data using JSON string or python dict rules in a PySpark environment.

pyspark-anonymizer Python library which makes it possible to dynamically mask/anonymize data using JSON string or python dict rules in a PySpark envir

null 6 Jun 30, 2022
Educational python for Neural Networks, written in pure Python/NumPy.

Educational python for Neural Networks, written in pure Python/NumPy.

null 127 Oct 27, 2022
A python library for easy manipulation and forecasting of time series.

Time Series Made Easy in Python darts is a python library for easy manipulation and forecasting of time series. It contains a variety of models, from

Unit8 5.2k Jan 4, 2023
STUMPY is a powerful and scalable Python library for computing a Matrix Profile, which can be used for a variety of time series data mining tasks

STUMPY STUMPY is a powerful and scalable library that efficiently computes something called the matrix profile, which can be used for a variety of tim

TD Ameritrade 2.5k Jan 6, 2023
A Python library for detecting patterns and anomalies in massive datasets using the Matrix Profile

matrixprofile-ts matrixprofile-ts is a Python 2 and 3 library for evaluating time series data using the Matrix Profile algorithms developed by the Keo

Target 696 Dec 26, 2022
ELI5 is a Python package which helps to debug machine learning classifiers and explain their predictions

A library for debugging/inspecting machine learning classifiers and explaining their predictions

null 154 Dec 17, 2022
A Python Module That Uses ANN To Predict A Stocks Price And Also Provides Accurate Technical Analysis With Many High Potential Implementations!

Stox A Module to predict the "close price" for the next day and give "technical analysis". It uses a Neural Network and the LSTM algorithm to predict

Stox 31 Dec 16, 2022
A Python-based application demonstrating various search algorithms, namely Depth-First Search (DFS), Breadth-First Search (BFS), and A* Search (Manhattan Distance Heuristic)

A Python-based application demonstrating various search algorithms, namely Depth-First Search (DFS), Breadth-First Search (BFS), and the A* Search (using the Manhattan Distance Heuristic)

null 17 Aug 14, 2022