scipplan 0.1.0a1__py2.py3-none-any.whl → 0.1.0a3__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scipplan/__init__.py +2 -2
- scipplan/config.py +6 -4
- scipplan/parse_model.py +68 -24
- scipplan/scipplan.py +21 -8
- {scipplan-0.1.0a1.dist-info → scipplan-0.1.0a3.dist-info}/METADATA +3 -3
- {scipplan-0.1.0a1.dist-info → scipplan-0.1.0a3.dist-info}/RECORD +10 -10
- {scipplan-0.1.0a1.dist-info → scipplan-0.1.0a3.dist-info}/LICENSE +0 -0
- {scipplan-0.1.0a1.dist-info → scipplan-0.1.0a3.dist-info}/WHEEL +0 -0
- {scipplan-0.1.0a1.dist-info → scipplan-0.1.0a3.dist-info}/entry_points.txt +0 -0
- {scipplan-0.1.0a1.dist-info → scipplan-0.1.0a3.dist-info}/top_level.txt +0 -0
    
        scipplan/__init__.py
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 | 
            -
            __version__ = "0.1. | 
| 1 | 
            +
            __version__ = "0.1.0alpha3"
         | 
| 2 2 | 
             
            print(f"SCIPPlan Version: {__version__}")
         | 
| 3 3 | 
             
            __release__ = "v0.1.0"
         | 
| 4 4 | 
             
            __author__ = "Ari Gestetner, Buser Say"
         | 
| 5 | 
            -
            __email__ = " | 
| 5 | 
            +
            __email__ = "ari.gestetner@monash.edu, buser.say@monash.edu"
         | 
    
        scipplan/config.py
    CHANGED
    
    | @@ -32,17 +32,17 @@ class Config: | |
| 32 32 | 
             
                        "gap": False
         | 
| 33 33 | 
             
                    }
         | 
| 34 34 | 
             
                    if self.horizon is None:
         | 
| 35 | 
            -
                        print("Horizon is not provided, and is set to 1")
         | 
| 35 | 
            +
                        print("Horizon is not provided, and is set to 1. ")
         | 
| 36 36 | 
             
                        self.horizon = 1
         | 
| 37 37 | 
             
                        self._defaults["horizon"] = True
         | 
| 38 38 |  | 
| 39 39 | 
             
                    if self.epsilon is None:
         | 
| 40 | 
            -
                        print("Epsilon is not provided, and is set to 0.1")
         | 
| 40 | 
            +
                        print("Epsilon is not provided, and is set to 0.1. ")
         | 
| 41 41 | 
             
                        self.epsilon = 0.1
         | 
| 42 42 | 
             
                        self._defaults["epsilon"] = True
         | 
| 43 43 |  | 
| 44 44 | 
             
                    if self.gap is None:
         | 
| 45 | 
            -
                        print("Gap is not provided, and is set to 10.0 | 
| 45 | 
            +
                        print("Gap is not provided, and is set to 10.0%. ")
         | 
| 46 46 | 
             
                        self.gap = 0.1
         | 
| 47 47 | 
             
                        self._defaults["gap"] = True
         | 
| 48 48 |  | 
| @@ -64,9 +64,11 @@ class Config: | |
| 64 64 | 
             
                    return dedent(text)
         | 
| 65 65 |  | 
| 66 66 | 
             
                def increment_horizon(self, value: int = 1):
         | 
| 67 | 
            -
                    self._defaults["horizon"] = False
         | 
| 67 | 
            +
                    # self._defaults["horizon"] = False
         | 
| 68 68 | 
             
                    self.horizon += value
         | 
| 69 69 |  | 
| 70 | 
            +
                def get_defaults(self) -> dict[str, bool]:
         | 
| 71 | 
            +
                    return self._defaults
         | 
| 70 72 |  | 
| 71 73 | 
             
                @classmethod
         | 
| 72 74 | 
             
                def get_config(cls) -> Config:
         | 
    
        scipplan/parse_model.py
    CHANGED
    
    | @@ -10,13 +10,68 @@ from math import exp, log, sqrt, sin, cos, isclose | |
| 10 10 |  | 
| 11 11 | 
             
            from pyscipopt.scip import Model, SumExpr
         | 
| 12 12 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
                 | 
| 16 | 
            -
                 | 
| 17 | 
            -
                 | 
| 18 | 
            -
                 | 
| 19 | 
            -
                 | 
| 13 | 
            +
             | 
| 14 | 
            +
            def linearise(expr: ast.Compare, aux_var: Variable) -> tuple[ast.Compare, ast.Compare]:
         | 
| 15 | 
            +
                """linearise
         | 
| 16 | 
            +
                This function linearises an inequality using an auxilary variable
         | 
| 17 | 
            +
                
         | 
| 18 | 
            +
                The linearisation process is as follows.
         | 
| 19 | 
            +
                If the expression is of the form of E1 <= E2, then we linearise by using the following expressions.
         | 
| 20 | 
            +
                z=0 ==> E1 <= E2 and z=1 ==> E1 > E2 (equivalent to E1 >= E2 + feastol). This is then equivalent to,
         | 
| 21 | 
            +
                E2 + feastol - M + z*M <= E1 <= E2 + zM.
         | 
| 22 | 
            +
                
         | 
| 23 | 
            +
                Similarly, for E1 < E2 we have z=0 ==> E1 < E2 which is equivalent to E1 <= E2 - feastol + z*M 
         | 
| 24 | 
            +
                and z=1 ==> E1 >= E2.
         | 
| 25 | 
            +
                Thus for E1 < E2 we have,
         | 
| 26 | 
            +
                E2 + z*M - M <= E1 <= E2 + z*M - feastol.
         | 
| 27 | 
            +
                
         | 
| 28 | 
            +
                If, however, the inequality is of the form of E1 >= E2 then we evaluate the expression, E2 <= E1.
         | 
| 29 | 
            +
                Similarly, if the expression is E1 > E2 then we evaluate the expression E2 < E1.
         | 
| 30 | 
            +
                
         | 
| 31 | 
            +
                :param expr: An inequality expression which is linearised.
         | 
| 32 | 
            +
                :type expr: ast.Compare
         | 
| 33 | 
            +
                :param aux_var: An auxiliary variable used when linearising the inequality to determine if the expression is true or false.
         | 
| 34 | 
            +
                :type aux_var: Variable
         | 
| 35 | 
            +
                :raises ValueError: If expr is not a valid inequality (i.e. doesn't use <, <=, > and >=)
         | 
| 36 | 
            +
                :return: both the linearised inequalities
         | 
| 37 | 
            +
                :rtype: tuple[ast.Compare, ast.Compare]
         | 
| 38 | 
            +
                """
         | 
| 39 | 
            +
                if not isinstance(expr.ops[0], (ast.Lt, ast.LtE, ast.Gt, ast.GtE)):
         | 
| 40 | 
            +
                    raise ValueError("Only <, <=, > or >= are allowed")
         | 
| 41 | 
            +
                if isinstance(expr.ops[0], ast.GtE):
         | 
| 42 | 
            +
                    expr.left, expr.comparators[0] = expr.comparators[0], expr.left
         | 
| 43 | 
            +
                    expr.ops[0] = ast.LtE()
         | 
| 44 | 
            +
                if isinstance(expr.ops[0], ast.Gt):
         | 
| 45 | 
            +
                    expr.left, expr.comparators[0] = expr.comparators[0], expr.left
         | 
| 46 | 
            +
                    expr.ops[0] = ast.Lt()
         | 
| 47 | 
            +
                
         | 
| 48 | 
            +
                if isinstance(expr.ops[0], ast.LtE):
         | 
| 49 | 
            +
                    lhs = ast.BinOp(
         | 
| 50 | 
            +
                        left=expr.comparators[0], 
         | 
| 51 | 
            +
                        op=ast.Add(), 
         | 
| 52 | 
            +
                        right=ast.parse(f"feastol - bigM + {aux_var.name} * bigM").body[0].value
         | 
| 53 | 
            +
                    )
         | 
| 54 | 
            +
                    rhs = ast.BinOp(
         | 
| 55 | 
            +
                        left=expr.comparators[0], 
         | 
| 56 | 
            +
                        op=ast.Add(), 
         | 
| 57 | 
            +
                        right=ast.parse(f"{aux_var.name} * bigM").body[0].value
         | 
| 58 | 
            +
                    )
         | 
| 59 | 
            +
                if isinstance(expr.ops[0], ast.Lt):
         | 
| 60 | 
            +
                    lhs = ast.BinOp(
         | 
| 61 | 
            +
                        left=expr.comparators[0], 
         | 
| 62 | 
            +
                        op=ast.Add(), 
         | 
| 63 | 
            +
                        right=ast.parse(f"{aux_var.name} * bigM - bigM").body[0].value
         | 
| 64 | 
            +
                    )
         | 
| 65 | 
            +
                    rhs = ast.BinOp(
         | 
| 66 | 
            +
                        left=expr.comparators[0], 
         | 
| 67 | 
            +
                        op=ast.Add(), 
         | 
| 68 | 
            +
                        right=ast.parse(f"{aux_var.name} * bigM - feastol").body[0].value
         | 
| 69 | 
            +
                    )
         | 
| 70 | 
            +
                expr1 = ast.Compare(lhs, [ast.LtE()], [expr.left])
         | 
| 71 | 
            +
                expr2 = ast.Compare(expr.left, [ast.LtE()], [rhs])
         | 
| 72 | 
            +
                return expr1, expr2
         | 
| 73 | 
            +
                
         | 
| 74 | 
            +
             | 
| 20 75 |  | 
| 21 76 | 
             
            @dataclass
         | 
| 22 77 | 
             
            class Expressions:
         | 
| @@ -37,8 +92,8 @@ class Expressions: | |
| 37 92 |  | 
| 38 93 | 
             
            class ParserType(Enum):
         | 
| 39 94 | 
             
                """ParserType
         | 
| 40 | 
            -
                 | 
| 41 | 
            -
                 | 
| 95 | 
            +
                enum type CALCULATOR: Used to calculate using feastol
         | 
| 96 | 
            +
                enum type PARSER: Used to parse an expression and create the correct minlp constraints
         | 
| 42 97 | 
             
                """
         | 
| 43 98 | 
             
                CALCULATOR = "calculator"
         | 
| 44 99 | 
             
                PARSER = "parser"
         | 
| @@ -152,22 +207,11 @@ class ParseModel: | |
| 152 207 | 
             
                                        aux_vars.append(aux_var)
         | 
| 153 208 | 
             
                                        self.variables[aux_var.name] = aux_var.model_var
         | 
| 154 209 |  | 
| 155 | 
            -
                                         | 
| 156 | 
            -
                                            left=expr.left, 
         | 
| 157 | 
            -
                                            op=(ast.Add() if isinstance(expr.ops[0], (ast.Gt, ast.GtE)) else ast.Sub()), 
         | 
| 158 | 
            -
                                            right=ast.parse(f"bigM * {aux_var.name}").body[0].value
         | 
| 159 | 
            -
                                        )
         | 
| 160 | 
            -
                                        self.expressions.add_expressions(self.evaluate(expr))
         | 
| 210 | 
            +
                                        expr1, expr2 = linearise(expr, aux_var)
         | 
| 161 211 |  | 
| 162 | 
            -
                                         | 
| 163 | 
            -
                                        
         | 
| 164 | 
            -
             | 
| 165 | 
            -
                                            left=expr.comparators[0], 
         | 
| 166 | 
            -
                                            op=(ast.Add() if isinstance(expr.ops[0], (ast.Gt, ast.GtE)) else ast.Sub()), 
         | 
| 167 | 
            -
                                            right=ast.parse(f"feastol - bigM").body[0].value
         | 
| 168 | 
            -
                                        )
         | 
| 169 | 
            -
                                        
         | 
| 170 | 
            -
                                        self.expressions.add_expressions(self.evaluate(expr))
         | 
| 212 | 
            +
                                        self.expressions.add_expressions(self.evaluate(expr1))
         | 
| 213 | 
            +
                                        self.expressions.add_expressions(self.evaluate(expr2))
         | 
| 214 | 
            +
             | 
| 171 215 | 
             
                                    else:
         | 
| 172 216 | 
             
                                        raise Exception("or expressions may only be made up of inequalities")
         | 
| 173 217 | 
             
                                lhs = SumExpr()
         | 
    
        scipplan/scipplan.py
    CHANGED
    
    | @@ -130,9 +130,10 @@ class SCIPPlan: | |
| 130 130 |  | 
| 131 131 | 
             
                @classmethod
         | 
| 132 132 | 
             
                def solve(cls, config: Config) -> tuple[SCIPPlan, float]:
         | 
| 133 | 
            +
                    # Time total solve time including incrementing horizon
         | 
| 134 | 
            +
                    start_time = time.time()
         | 
| 133 135 | 
             
                    while True:
         | 
| 134 136 | 
             
                        model = SCIPPlan(config)
         | 
| 135 | 
            -
                        start_time = time.time()
         | 
| 136 137 | 
             
                        try:
         | 
| 137 138 | 
             
                            print(f"Encoding the problem over horizon h={config.horizon}.")
         | 
| 138 139 | 
             
                            print("Solving the problem.")
         | 
| @@ -144,12 +145,21 @@ class SCIPPlan: | |
| 144 145 | 
             
                            return model, solve_time 
         | 
| 145 146 |  | 
| 146 147 |  | 
| 147 | 
            -
                        except InfeasibilityError:
         | 
| 148 | 
            +
                        except InfeasibilityError:    
         | 
| 149 | 
            +
                            if config.get_defaults().get("horizon") is False:
         | 
| 150 | 
            +
                                print(f"Horizon of h={model.config.horizon} is infeasible.")
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                                solve_time = (time.time() - start_time)
         | 
| 153 | 
            +
                                print(f"Total time: {solve_time:.3f}")
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                                raise InfeasibilityError
         | 
| 156 | 
            +
                                
         | 
| 157 | 
            +
                            
         | 
| 148 158 | 
             
                            # print("Problem is infeasible for the given horizon.")
         | 
| 149 | 
            -
                            print(f"Horizon of h={model.config.horizon} is infeasible, incrementing to h={model.config.horizon + 1}")
         | 
| 159 | 
            +
                            print(f"Horizon of h={model.config.horizon} is infeasible, incrementing to h={model.config.horizon + 1}.")
         | 
| 150 160 | 
             
                            config.increment_horizon()
         | 
| 151 161 | 
             
                            if config.show_output is True:
         | 
| 152 | 
            -
                                print(f"Horizon Time: {(time.time() - start_time): .3f} seconds")
         | 
| 162 | 
            +
                                print(f"Horizon Time: {(time.time() - start_time): .3f} seconds.")
         | 
| 153 163 |  | 
| 154 164 |  | 
| 155 165 | 
             
                def save_values(self, iteration: int):
         | 
| @@ -162,8 +172,11 @@ def main(): | |
| 162 172 | 
             
                print(f"PySCIPOpt Version: {version('pyscipopt')}\n")
         | 
| 163 173 | 
             
                config = Config.get_config()
         | 
| 164 174 | 
             
                print(config)
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                 | 
| 175 | 
            +
                
         | 
| 176 | 
            +
                try:
         | 
| 177 | 
            +
                    plan, solve_time = SCIPPlan.solve(config)  
         | 
| 178 | 
            +
                except InfeasibilityError:
         | 
| 179 | 
            +
                    return None
         | 
| 167 180 |  | 
| 168 181 | 
             
                if config.save_sols is True:
         | 
| 169 182 | 
             
                    write_to_csv("new_constraints", plan.new_constraints, config)
         | 
| @@ -185,9 +198,9 @@ def main(): | |
| 185 198 | 
             
                    for action_name in action_names:
         | 
| 186 199 | 
             
                        if action_name == config.dt_var:
         | 
| 187 200 | 
             
                            continue
         | 
| 188 | 
            -
                        print(f"{action_name} at step {step} by value {plan.scip_model.getVal(plan.plan.variables[(action_name, step)].model_var):.3f}")
         | 
| 201 | 
            +
                        print(f"{action_name} at step {step} by value {plan.scip_model.getVal(plan.plan.variables[(action_name, step)].model_var):.3f}.")
         | 
| 189 202 |  | 
| 190 | 
            -
                    print(f"Dt at step {step} by value {plan.scip_model.getVal(plan.plan.variables[('Dt', step)].model_var):.3f} \n")
         | 
| 203 | 
            +
                    print(f"Dt at step {step} by value {plan.scip_model.getVal(plan.plan.variables[('Dt', step)].model_var):.3f}. \n")
         | 
| 191 204 |  | 
| 192 205 | 
             
                print(f"Total reward: {(plan.scip_model.getObjVal()):.3f}")
         | 
| 193 206 | 
             
                print(f"Total time: {solve_time:.3f}")
         | 
| @@ -1,9 +1,9 @@ | |
| 1 1 | 
             
            Metadata-Version: 2.1
         | 
| 2 2 | 
             
            Name: scipplan
         | 
| 3 | 
            -
            Version: 0.1. | 
| 3 | 
            +
            Version: 0.1.0a3
         | 
| 4 4 | 
             
            Summary: Metric Hybrid Factored Planning in Nonlinear Domains with Constraint Generation in Python.
         | 
| 5 5 | 
             
            Author: Ari Gestetner, Buser Say
         | 
| 6 | 
            -
            Author-email:  | 
| 6 | 
            +
            Author-email: ari.gestetner@monash.edu, buser.say@monash.edu
         | 
| 7 7 | 
             
            License: MIT License
         | 
| 8 8 | 
             
            Keywords: scip,automated planner
         | 
| 9 9 | 
             
            Classifier: Development Status :: 3 - Alpha
         | 
| @@ -144,7 +144,7 @@ Location_y == 0.0 | |
| 144 144 | 
             
            Speed_x == 0.0
         | 
| 145 145 | 
             
            Speed_y == 0.0
         | 
| 146 146 | 
             
            ```
         | 
| 147 | 
            -
            notice  | 
| 147 | 
            +
            notice the use of the constant value defined earlier in the constants file.
         | 
| 148 148 | 
             
            ### Goals
         | 
| 149 149 | 
             
            The goals file should encode the final state values such that t=H+1, for example
         | 
| 150 150 | 
             
            ```txt
         | 
| @@ -1,9 +1,9 @@ | |
| 1 | 
            -
            scipplan/__init__.py,sha256= | 
| 2 | 
            -
            scipplan/config.py,sha256= | 
| 1 | 
            +
            scipplan/__init__.py,sha256=KScjrF1mIQbNUpdz4Ln6Ig5eA4ExpSUKSd1crpjyuv4,193
         | 
| 2 | 
            +
            scipplan/config.py,sha256=0D6UcLjrv4PTjYRiPoIYXAsRu4nwcaOIWnsI4lAdK6Y,5221
         | 
| 3 3 | 
             
            scipplan/helpers.py,sha256=YwEr0NeDvb29_Ot686km3ZMJ-vHu-L8zjuexmlKDjpY,974
         | 
| 4 | 
            -
            scipplan/parse_model.py,sha256 | 
| 4 | 
            +
            scipplan/parse_model.py,sha256=CI_38xmaiVr8DuOi3UdNrVqWHTdW6qm_5luwLZxIk9I,11136
         | 
| 5 5 | 
             
            scipplan/plan_model.py,sha256=daHnVHn2e89OtXXMl63QEoeKGOmy_LwT2oCRTjUUlKQ,11145
         | 
| 6 | 
            -
            scipplan/scipplan.py,sha256= | 
| 6 | 
            +
            scipplan/scipplan.py,sha256=z6cuRug4amCg6LU7S4RYHcV6uT3vWLHYGRh9OXFkKoU,8225
         | 
| 7 7 | 
             
            scipplan/variables.py,sha256=3sxY3zQuxsa5z2fTFjv4zOSb9GarzojZ4W4kIx9FX68,2561
         | 
| 8 8 | 
             
            scipplan/zero_crossing.py,sha256=kGyJsWZLLXqLW1p3LPDlPC34rTkFF8daDzqgbEcaXus,1043
         | 
| 9 9 | 
             
            scipplan/translation/constants_navigation_1.txt,sha256=X0jvJe5MiwvayKBVXo9TQlGZGfUlpnFpMiReL68rsXc,43
         | 
| @@ -30,9 +30,9 @@ scipplan/translation/temporal_constraints_navigation_3.txt,sha256=Ki4nAX9-QtBbY9 | |
| 30 30 | 
             
            scipplan/translation/transitions_navigation_1.txt,sha256=kfnr3_A9mCfflLsL4aq7OeR_BHSNST6eYuAg4ZxaPoU,411
         | 
| 31 31 | 
             
            scipplan/translation/transitions_navigation_2.txt,sha256=kfnr3_A9mCfflLsL4aq7OeR_BHSNST6eYuAg4ZxaPoU,411
         | 
| 32 32 | 
             
            scipplan/translation/transitions_navigation_3.txt,sha256=aIPP3FOjXZ3G6sTqicEIZ0JKJxdxHCRRZIdc5bUPFBM,395
         | 
| 33 | 
            -
            scipplan-0.1. | 
| 34 | 
            -
            scipplan-0.1. | 
| 35 | 
            -
            scipplan-0.1. | 
| 36 | 
            -
            scipplan-0.1. | 
| 37 | 
            -
            scipplan-0.1. | 
| 38 | 
            -
            scipplan-0.1. | 
| 33 | 
            +
            scipplan-0.1.0a3.dist-info/LICENSE,sha256=tfR4peJA8KJtYEn1NzNV-LWQVRAserdq7OJgYghreR0,1057
         | 
| 34 | 
            +
            scipplan-0.1.0a3.dist-info/METADATA,sha256=O1UnTCpE4vAdV1zmtvJ5jJKcqTErpVtxjlwHE9BO2wg,11234
         | 
| 35 | 
            +
            scipplan-0.1.0a3.dist-info/WHEEL,sha256=-G_t0oGuE7UD0DrSpVZnq1hHMBV9DD2XkS5v7XpmTnk,110
         | 
| 36 | 
            +
            scipplan-0.1.0a3.dist-info/entry_points.txt,sha256=3qiNbbp6qIwivyPmmikyp7ByCfmsa9rGFNJPcN9Is8I,52
         | 
| 37 | 
            +
            scipplan-0.1.0a3.dist-info/top_level.txt,sha256=xO2FLRn7YQ-C25E8lagIEbik5T5FTr-Ta5bdiZezEPY,9
         | 
| 38 | 
            +
            scipplan-0.1.0a3.dist-info/RECORD,,
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |