scipplan 0.1.1a0__py2.py3-none-any.whl → 0.2.0a1__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 CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.1.1alpha0"
1
+ __version__ = "0.2.0alpha1"
2
2
  print(f"SCIPPlan Version: {__version__}")
3
3
  __release__ = "v0.1.0"
4
4
  __author__ = "Ari Gestetner, Buser Say"
scipplan/config.py CHANGED
@@ -16,6 +16,7 @@ class Config:
16
16
  horizon: int = field(default=None)
17
17
  epsilon: float = field(default=None)
18
18
  gap: float = field(default=None)
19
+ provide_sols: bool = field(default=False)
19
20
  show_output: bool = False
20
21
  save_sols: bool = False
21
22
  bigM: float = 1000.0
@@ -50,6 +51,7 @@ class Config:
50
51
  text = f"""
51
52
  Configuration:
52
53
 
54
+ Use System of ODE's: {not self.provide_sols}
53
55
  Display SCIP Output: {self.show_output}
54
56
  Save Solutions: {self.show_output}
55
57
  Dt Variable Name: {self.dt_var}
@@ -80,14 +82,14 @@ class Config:
80
82
  "--domain",
81
83
  required=True,
82
84
  type=str,
83
- help="This variable is the name of the domain (e.g. pandemic or navigation)"
85
+ help="This variable is the name of the domain (e.g. pandemic or navigation)."
84
86
  )
85
87
  parser.add_argument(
86
88
  "-I",
87
89
  "--instance",
88
90
  required=True,
89
91
  type=str,
90
- help="This is the instance number of the domain (e.g. navigation has instances 1, 2 and 3)"
92
+ help="This is the instance number of the domain (e.g. navigation has instances 1, 2 and 3)."
91
93
  )
92
94
  parser.add_argument(
93
95
  "-H",
@@ -95,7 +97,7 @@ class Config:
95
97
  required=False,
96
98
  # default=1,
97
99
  type=int,
98
- help="The initial horizon. The solve method will initially begin with this horizon until it finds a feasible solution"
100
+ help="The initial horizon. The solve method will initially begin with this horizon until it finds a feasible solution."
99
101
  )
100
102
  parser.add_argument(
101
103
  "-E",
@@ -103,7 +105,7 @@ class Config:
103
105
  required=False,
104
106
  # default=0.1,
105
107
  type=float,
106
- help="SCIPPlan iteratively checks solution for violations at each epsilon value"
108
+ help="SCIPPlan iteratively checks solution for violations at each epsilon value."
107
109
  )
108
110
  parser.add_argument(
109
111
  "-G",
@@ -111,7 +113,7 @@ class Config:
111
113
  required=False,
112
114
  # default=0.1,
113
115
  type=float,
114
- help="SCIP will search for solution with an optimality gap by at least this value"
116
+ help="SCIP will search for solution with an optimality gap by at least this value."
115
117
  )
116
118
 
117
119
  parser.add_argument(
@@ -119,7 +121,7 @@ class Config:
119
121
  required=False,
120
122
  default=1000.0,
121
123
  type=float,
122
- help="A large value which is used for some constraint encoding formulations, defaults to 1000.0 and can be changed as needed"
124
+ help="A large value which is used for some constraint encoding formulations, defaults to 1000.0 and can be changed as needed."
123
125
  )
124
126
 
125
127
  parser.add_argument(
@@ -127,21 +129,28 @@ class Config:
127
129
  required=False,
128
130
  default="Dt",
129
131
  type=str,
130
- help="When writing the constraints, dt_var is the variable name for Dt, defaults to 'Dt' and can be changed based on users preference (e.g. 'dt')"
132
+ help="When writing the constraints, dt_var is the variable name for Dt, defaults to 'Dt' and can be changed based on users preference (e.g. 'dt')."
131
133
  )
132
134
 
135
+ parser.add_argument(
136
+ "--provide-sols",
137
+ action="store_true",
138
+ default=False,
139
+ help="This flag determines whether the user would like to provide a system of odes or solution equations, odes must be provided by default."
140
+ )
141
+
133
142
  parser.add_argument(
134
143
  "--show-output",
135
144
  action="store_true",
136
145
  default=False,
137
- help="Include this flag to show output from SCIP"
146
+ help="Include this flag to show output from SCIP."
138
147
  )
139
148
 
140
149
  parser.add_argument(
141
150
  "--save-sols",
142
151
  action="store_true",
143
152
  default=False,
144
- help="Include this flag to save the solutions from each of the scipplan iterations as well as constraints generated (note, only saves for horizon which has been solved)"
153
+ help="Include this flag to save the solutions from each of the scipplan iterations as well as constraints generated (note, only saves for horizon which has been solved)."
145
154
  )
146
155
 
147
156
  args = parser.parse_args()
scipplan/helpers.py CHANGED
@@ -2,6 +2,7 @@ import os
2
2
  import csv
3
3
 
4
4
  from typing import Generator
5
+
5
6
  from .config import Config
6
7
 
7
8
  class InfeasibilityError(Exception):
scipplan/parse_model.py CHANGED
@@ -10,68 +10,13 @@ from math import exp, log, sqrt, sin, cos, isclose
10
10
 
11
11
  from pyscipopt.scip import Model, SumExpr
12
12
 
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
-
13
+ def switch_comparator(comparator):
14
+ if isinstance(comparator, ast.Eq): return ast.NotEq()
15
+ if isinstance(comparator, ast.NotEq): return ast.Eq()
16
+ if isinstance(comparator, ast.Lt): return ast.Gt()
17
+ if isinstance(comparator, ast.LtE): return ast.GtE()
18
+ if isinstance(comparator, ast.Gt): return ast.Lt()
19
+ if isinstance(comparator, ast.GtE): return ast.LtE()
75
20
 
76
21
  @dataclass
77
22
  class Expressions:
@@ -92,8 +37,8 @@ class Expressions:
92
37
 
93
38
  class ParserType(Enum):
94
39
  """ParserType
95
- enum type CALCULATOR: Used to calculate using feastol
96
- enum type PARSER: Used to parse an expression and create the correct minlp constraints
40
+ "enum type CALCULATOR: Used to calculate using feastol
41
+ "enum type PARSER: Used to parse an expression and create the correct minlp constraints
97
42
  """
98
43
  CALCULATOR = "calculator"
99
44
  PARSER = "parser"
@@ -207,11 +152,22 @@ class ParseModel:
207
152
  aux_vars.append(aux_var)
208
153
  self.variables[aux_var.name] = aux_var.model_var
209
154
 
210
- expr1, expr2 = linearise(expr, aux_var)
155
+ expr.left = ast.BinOp(
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))
211
161
 
212
- self.expressions.add_expressions(self.evaluate(expr1))
213
- self.expressions.add_expressions(self.evaluate(expr2))
214
-
162
+ expr.ops[0] = switch_comparator(expr.ops[0])
163
+
164
+ expr.comparators[0] = ast.BinOp(
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))
215
171
  else:
216
172
  raise Exception("or expressions may only be made up of inequalities")
217
173
  lhs = SumExpr()
scipplan/plan_model.py CHANGED
@@ -9,6 +9,9 @@ import os
9
9
  from pyscipopt.scip import Model
10
10
  from pkg_resources import parse_version
11
11
  from importlib.metadata import version
12
+ from sympy import Eq, Function, Derivative as dd, Symbol, parse_expr
13
+ from sympy.solvers.ode.systems import dsolve_system
14
+
12
15
 
13
16
  if parse_version(version("pyscipopt")) >= parse_version("4.3.0"):
14
17
  from pyscipopt import quicksum, exp, log, sqrt, sin, cos
@@ -27,6 +30,8 @@ class PlanModel:
27
30
  # Translation -> line_num -> horizon -> aux
28
31
  self.aux_vars: dict[str, list[list[list]]] = {}
29
32
 
33
+ self.file_translations = self.read_translations()
34
+
30
35
  self.constants = self.encode_constants()
31
36
  self.variables = self.encode_pvariables()
32
37
  self.translations = self.encode_constraints()
@@ -39,8 +44,27 @@ class PlanModel:
39
44
  self.model.addCons(dt_var >= 0.0, f"dt_{h}_lower_bound")
40
45
  self.model.addCons(dt_var <= self.config.bigM, f"dt_{h}_upper_bound")
41
46
 
42
-
47
+ def read_translations(self) -> dict[str, list[str]]:
48
+ with open(self.get_file_path("solutions" if self.config.provide_sols else "odes")) as f:
49
+ translations = {}
50
+ new_sec = True
51
+ for line in f:
52
+ line = line.strip()
53
+ if line == "":
54
+ pass
55
+ elif line == "---":
56
+ new_sec = True
57
+ elif new_sec is True:
58
+ translation = line.removesuffix(":")
59
+ translations[translation] = []
60
+ new_sec = False
61
+ else:
62
+ translations[translation].append(line)
43
63
 
64
+ return translations
65
+
66
+
67
+
44
68
  def encode_constants(self) -> dict[str, float]:
45
69
  constants = {}
46
70
  translation = "constants"
@@ -53,23 +77,20 @@ class PlanModel:
53
77
  }
54
78
 
55
79
 
56
- with open(self.get_file_path(translation)) as f:
57
- for line in f.readlines():
58
- if line.strip() == "":
59
- continue
60
-
61
- var, val = line.strip().split("=")
62
- var, val = var.strip(), val.strip()
63
-
64
- val = val if val not in config_vals else config_vals[val]
65
-
66
- try:
67
- val = float(val)
68
- except ValueError:
69
- raise ValueError("Constants can only be floats, please reconfigure: ")
70
-
71
- constants[var] = val
72
- self.var_names.add(var)
80
+ for line in self.file_translations[translation]:
81
+
82
+ var, val = line.split("=")
83
+ var, val = var.strip(), val.strip()
84
+
85
+ val = val if val not in config_vals else config_vals[val]
86
+
87
+ try:
88
+ val = float(val)
89
+ except ValueError:
90
+ raise ValueError("Constants can only be floats, please reconfigure: ")
91
+
92
+ constants[var] = val
93
+ self.var_names.add(var)
73
94
 
74
95
  constants["bigM"] = self.config.bigM
75
96
  self.var_names.add("bigM")
@@ -84,28 +105,22 @@ class PlanModel:
84
105
  var_type = variables[(constant, t)].var_type
85
106
 
86
107
  translation = "pvariables"
87
- with open(self.get_file_path(translation)) as f:
88
- for line in f.readlines():
89
-
90
- var = line.rstrip("\n").strip()
91
- if var == "":
92
- continue
93
- vtype, name = var.split(": ")
94
- vtype, name = vtype.strip(), name.strip()
95
-
96
- self.var_names.add(name)
97
-
98
- if vtype.startswith("global"):
99
- var = Variable.create_var(self.model, name, vtype, "global", self.constants)
100
- for t in range(self.config.horizon + 1):
101
- variables[(name, t)] = var
102
- else:
103
- for t in range(self.config.horizon):
104
- variables[(name, t)] = Variable.create_var(self.model, name, vtype, t, self.constants)
105
- var_type = variables[(name, t)].var_type
106
- if var_type is VarType.STATE:
107
- variables[(name, self.config.horizon)] = Variable.create_var(self.model, name, vtype, self.config.horizon, self.constants)
108
-
108
+ for line in self.file_translations[translation]:
109
+
110
+ var = line.rstrip("\n").strip()
111
+ if var == "":
112
+ continue
113
+ vtype, name = var.split(": ")
114
+ vtype, name = vtype.strip(), name.strip()
115
+
116
+ self.var_names.add(name)
117
+
118
+ for t in range(self.config.horizon):
119
+ variables[(name, t)] = Variable.create_var(self.model, name, vtype, t, self.constants)
120
+ var_type = variables[(name, t)].var_type
121
+ if var_type is VarType.STATE:
122
+ variables[(name, self.config.horizon)] = Variable.create_var(self.model, name, vtype, self.config.horizon, self.constants)
123
+
109
124
  return variables
110
125
 
111
126
 
@@ -116,24 +131,37 @@ class PlanModel:
116
131
  "instantaneous_constraints",
117
132
  "temporal_constraints",
118
133
  "goals",
119
- "transitions"
134
+ "odes" if self.config.provide_sols is False else "transitions"
120
135
  ]
121
136
  translations: dict[str, list[str]] = {}
122
137
  for translation in translation_names:
123
138
  translations[translation] = []
124
139
 
125
- with open(self.get_file_path(translation)) as f:
126
- for line in f.readlines():
127
- expr = line.rstrip("\n").strip()
128
- # If line is empty don't append
129
- if expr == "":
130
- continue
131
-
132
- translations[translation].append(expr)
140
+ for line in self.file_translations[translation]:
141
+ expr = line.rstrip("\n").strip()
142
+ # If line is empty don't append
143
+ if expr == "":
144
+ continue
145
+
146
+ translations[translation].append(expr)
147
+
148
+ if self.config.provide_sols is False:
149
+ self.ode_functions = self.solve_odes(translations["odes"])
150
+
151
+ translations["transitions"] = []
152
+ for func_name, func in self.ode_functions.items():
153
+ translations["transitions"].append((func_name + "_dash" + " == " + func))
154
+
155
+ del translations["odes"]
133
156
 
157
+
134
158
  # Encode constraints into model
135
159
  for cons_idx, (translation, constraints) in enumerate(translations.items()):
136
160
  for idx, constraint in enumerate(constraints):
161
+ if (self.config.provide_sols is False) and (translation == "temporal_constraints"):
162
+ for func_name, func in self.ode_functions.items():
163
+ constraint = constraint.replace(func_name, func)
164
+ constraints[idx] = constraint
137
165
  if translation == "initials":
138
166
  exprs = PM(self.get_parser_params(horizon=0, add_aux_vars=True)).evaluate(constraint, horizon=0, expr_name=f"{translation}_{idx}_0")
139
167
 
@@ -170,16 +198,15 @@ class PlanModel:
170
198
  def encode_reward(self):
171
199
  objectives = [None] * self.config.horizon
172
200
  translation = "reward"
173
- with open(self.get_file_path(translation)) as f:
174
- reward = f.readline().rstrip("\n")
175
- for t in range(self.config.horizon):
176
- objectives[t] = self.model.addVar(f"Obj_{t}", vtype="C", lb=None, ub=None)
177
- # For the sake of similarity the reward is similar to constraint parsing, however, only one reward function is allowed
178
- exprs = PM(self.get_parser_params(t)).evaluate(reward)
179
- for expr_idx, expr in enumerate(exprs):
180
- self.model.addCons(objectives[t] == expr, f"Obj_{t}_{expr_idx}")
181
-
182
- self.model.setObjective(quicksum(objectives), "maximize")
201
+ reward = self.file_translations[translation][0]
202
+ for t in range(self.config.horizon):
203
+ objectives[t] = self.model.addVar(f"Obj_{t}", vtype="C", lb=None, ub=None)
204
+ # For the sake of similarity the reward is similar to constraint parsing, however, only one reward function is allowed
205
+ exprs = PM(self.get_parser_params(t)).evaluate(reward)
206
+ for expr_idx, expr in enumerate(exprs):
207
+ self.model.addCons(objectives[t] == expr, f"Obj_{t}_{expr_idx}")
208
+
209
+ self.model.setObjective(quicksum(objectives), "maximize")
183
210
 
184
211
  return objectives
185
212
 
@@ -259,4 +286,47 @@ class PlanModel:
259
286
  return os.path.join(pkg_files_path, path)
260
287
  else:
261
288
  raise Exception("Unkown file name, please enter a configuration for a valid domain instance in translation: ")
262
-
289
+
290
+
291
+ def solve_odes(self, ode_system: list[str]) -> dict[str, str]:
292
+ dt_var = self.config.dt_var
293
+
294
+ dt = Symbol(dt_var)
295
+ # Used to represent constant variables
296
+ temp_var = Symbol("TEMP_VAR")
297
+
298
+ variables = {}
299
+ states = []
300
+
301
+ for var_name in self.var_names:
302
+ var = self.variables[(var_name, 0)]
303
+ if var.var_type is VarType.STATE:
304
+ states.append(var.name)
305
+ variables[var.name] = Function(var.name)(dt)
306
+ elif var.var_type is VarType.CONSTANT:
307
+ variables[var.name] = self.constants[var.name]
308
+ else: # the variable is an action or aux variable which is encoded as a function of some unused variable as workaround to not being able to use symbols for constants
309
+ variables[var.name] = Function(var.name)(temp_var)
310
+
311
+ variables[dt_var] = dt
312
+
313
+ system = []
314
+ for eqtn in ode_system:
315
+ lhs, rhs = eqtn.split("==")
316
+ lhs = parse_expr(lhs.strip(), local_dict=variables | {"dd": dd})
317
+ rhs = parse_expr(rhs.strip(), local_dict=variables | {"dd": dd})
318
+ system.append(Eq(lhs, rhs))
319
+ results = dsolve_system(system, ics={variables[state].subs(dt, 0): state for state in states})
320
+
321
+
322
+
323
+ functions: dict[str, str] = {}
324
+ for eqtn in results[0]:
325
+ new_eqtn = eqtn.doit()
326
+ func_name = new_eqtn.lhs.name.replace(f"({temp_var.name})", "").replace(f"({self.config.dt_var})", "_dash")
327
+ functions[func_name] = str(new_eqtn.rhs).replace(f"({temp_var.name})", "").replace(f"({self.config.dt_var})", "_dash")
328
+
329
+
330
+ return functions
331
+
332
+
scipplan/scipplan.py CHANGED
@@ -46,6 +46,8 @@ class SCIPPlan:
46
46
  def optimize(self):
47
47
  iteration = 0
48
48
 
49
+ const_gen_aux_vars = [[None] * self.config.horizon for _ in range(len(self.plan.translations["temporal_constraints"]))]
50
+
49
51
  while True:
50
52
  self.scip_model.optimize()
51
53
 
@@ -80,10 +82,15 @@ class SCIPPlan:
80
82
 
81
83
  for idx, constraint in enumerate(self.plan.translations["temporal_constraints"]):
82
84
  t = zero_cross.horizon
83
- aux_vars = self.plan.aux_vars["temporal_constraints"][idx][t]
84
- params = self.plan.get_parser_params(horizon=t)
85
+ # aux_vars = self.plan.aux_vars["temporal_constraints"][idx][t]
86
+ aux_vars = const_gen_aux_vars[idx][t]
87
+ # Only add aux vars if there are no aux vars added for the secific constraint
88
+ params = self.plan.get_parser_params(horizon=t, add_aux_vars=aux_vars is None)
85
89
  params.variables[self.config.dt_var] *= zero_cross.coef
86
90
  exprs = PM(params).evaluate(constraint, aux_vars=aux_vars)
91
+ if const_gen_aux_vars[idx][t] is None:
92
+ const_gen_aux_vars[idx][t] = exprs.aux_vars
93
+
87
94
  for eqtn_idx, eqtn in enumerate(exprs):
88
95
  self.plan.model.addCons(eqtn, f"{constraint}_{idx}_{eqtn_idx}")
89
96
 
@@ -0,0 +1,50 @@
1
+ constants:
2
+ Epsilon = config_epsilon
3
+ bigM = config_bigM
4
+ ---
5
+ pvariables:
6
+ action_continuous: Accelerate_x
7
+ action_continuous: Accelerate_y
8
+ action_continuous: Dt
9
+ state_continuous: Location_x
10
+ state_continuous: Location_y
11
+ state_continuous: Speed_x
12
+ state_continuous: Speed_y
13
+ ---
14
+ odes:
15
+ dd(Location_x, Dt) == Speed_x
16
+ dd(Location_y, Dt) == Speed_y
17
+ dd(Speed_x, Dt) == Accelerate_x
18
+ dd(Speed_y, Dt) == Accelerate_y
19
+ ---
20
+ initials:
21
+ Location_x == 0.0
22
+ Location_y == 0.0
23
+ Speed_x == 0.0
24
+ Speed_y == 0.0
25
+ ---
26
+ instantaneous_constraints:
27
+ Location_x <= 10.0
28
+ Location_y <= 10.0
29
+ Location_x >= 0.0
30
+ Location_y >= 0.0
31
+ Accelerate_x <= 0.5
32
+ Accelerate_y <= 0.5
33
+ Accelerate_x >= -0.5
34
+ Accelerate_y >= -0.5
35
+ (Location_x <= 4.0) or (Location_x >= 6.0) or (Location_y <= 4.0) or (Location_y >= 6.0)
36
+ ---
37
+ temporal_constraints:
38
+ Location_x <= 10.0
39
+ Location_y <= 10.0
40
+ Location_x >= 0.0
41
+ Location_y >= 0.0
42
+
43
+ (Location_x <= 4.0) or (Location_x >= 6.0) or (Location_y <= 4.0) or (Location_y >= 6.0)
44
+ ---
45
+ goals:
46
+ Location_x == 8.0
47
+ Location_y == 8.0
48
+ ---
49
+ reward:
50
+ -1.0*(Dt)
@@ -0,0 +1,51 @@
1
+ constants:
2
+ Epsilon = config_epsilon
3
+ bigM = config_bigM
4
+ ---
5
+ pvariables:
6
+ action_continuous: Accelerate_x
7
+ action_continuous: Accelerate_y
8
+ action_continuous: Dt
9
+ state_continuous: Location_x
10
+ state_continuous: Location_y
11
+ state_continuous: Speed_x
12
+ state_continuous: Speed_y
13
+ ---
14
+ odes:
15
+ dd(Location_x, Dt) == Speed_x
16
+ dd(Location_y, Dt) == Speed_y
17
+ dd(Speed_x, Dt) == Accelerate_x
18
+ dd(Speed_y, Dt) == Accelerate_y
19
+ ---
20
+ initials:
21
+ Location_x == 0.0
22
+ Location_y == 0.0
23
+ Speed_x == 0.0
24
+ Speed_y == 0.0
25
+ ---
26
+ instantaneous_constraints:
27
+ Location_x <= 10.0
28
+ Location_y <= 10.0
29
+ Location_x >= 0.0
30
+ Location_y >= 0.0
31
+ Accelerate_x <= 0.5
32
+ Accelerate_y <= 0.5
33
+ Accelerate_x >= -0.5
34
+ Accelerate_y >= -0.5
35
+ (Location_x <= 2.0) or (Location_x >= 4.0) or (Location_y <= 1.0) or (Location_y >= 5.0)
36
+ (Location_x <= 5.0) or (Location_x >= 7.0) or (Location_y <= 5.0) or (Location_y >= 9.0)
37
+ ---
38
+ temporal_constraints:
39
+ Location_x <= 10.0
40
+ Location_y <= 10.0
41
+ Location_x >= 0.0
42
+ Location_y >= 0.0
43
+ (Location_x <= 2.0) or (Location_x >= 4.0) or (Location_y <= 1.0) or (Location_y >= 5.0)
44
+ (Location_x <= 5.0) or (Location_x >= 7.0) or (Location_y <= 5.0) or (Location_y >= 9.0)
45
+ ---
46
+ goals:
47
+ Location_x == 8.0
48
+ Location_y == 8.0
49
+ ---
50
+ reward:
51
+ -1.0*(Dt)
@@ -0,0 +1,53 @@
1
+ constants:
2
+ Epsilon = config_epsilon
3
+ bigM = config_bigM
4
+ ---
5
+ pvariables:
6
+ action_continuous: Accelerate_x
7
+ action_continuous: Accelerate_y
8
+ action_continuous: Dt
9
+ state_continuous: Location_x
10
+ state_continuous: Location_y
11
+ state_continuous: Speed_x
12
+ state_continuous: Speed_y
13
+ ---
14
+ odes:
15
+ dd(Location_x, Dt) == Speed_x
16
+ dd(Location_y, Dt) == Speed_y
17
+ dd(Speed_x, Dt) == Accelerate_x
18
+ dd(Speed_y, Dt) == Accelerate_y
19
+ ---
20
+ initials:
21
+ Location_x == 0.0
22
+ Location_y == 0.0
23
+ Speed_x == 0.0
24
+ Speed_y == 0.0
25
+ ---
26
+ instantaneous_constraints:
27
+ Location_x <= 10.0
28
+ Location_y <= 10.0
29
+ Location_x >= 0.0
30
+ Location_y >= 0.0
31
+ Accelerate_x <= 0.5
32
+ Accelerate_y <= 0.5
33
+ Accelerate_x >= -0.5
34
+ Accelerate_y >= -0.5
35
+ (Location_x <= 2.0) or (Location_x >= 4.0) or (Location_y <= 1.0) or (Location_y >= 9.0)
36
+ (Location_x <= 4.0) or (Location_x >= 7.0) or (Location_y <= 7.0) or (Location_y >= 9.0)
37
+ (Location_x <= 4.0) or (Location_x >= 9.0) or (Location_y <= 2.0) or (Location_y >= 6.0)
38
+ ---
39
+ temporal_constraints:
40
+ Location_x <= 10.0
41
+ Location_y <= 10.0
42
+ Location_x >= 0.0
43
+ Location_y >= 0.0
44
+ (Location_x <= 2.0) or (Location_x >= 4.0) or (Location_y <= 1.0) or (Location_y >= 9.0)
45
+ (Location_x <= 4.0) or (Location_x >= 7.0) or (Location_y <= 7.0) or (Location_y >= 9.0)
46
+ (Location_x <= 4.0) or (Location_x >= 9.0) or (Location_y <= 2.0) or (Location_y >= 6.0)
47
+ ---
48
+ goals:
49
+ Location_x == 8.0
50
+ Location_y == 8.0
51
+ ---
52
+ reward:
53
+ -1.0*(Dt)
@@ -0,0 +1,50 @@
1
+ constants:
2
+ Epsilon = config_epsilon
3
+ bigM = config_bigM
4
+ ---
5
+ pvariables:
6
+ action_continuous: Accelerate_x
7
+ action_continuous: Accelerate_y
8
+ action_continuous: Dt
9
+ state_continuous: Location_x
10
+ state_continuous: Location_y
11
+ state_continuous: Speed_x
12
+ state_continuous: Speed_y
13
+ ---
14
+ transitions:
15
+ Location_x_dash - 1.0*Location_x - 1.0*Speed_x*(Dt) - 0.5*Accelerate_x*(Dt)*(Dt) == 0.0
16
+ Location_y_dash - 1.0*Location_y - 1.0*Speed_y*(Dt) - 0.5*Accelerate_y*(Dt)*(Dt) == 0.0
17
+ Speed_x_dash - 1.0*Speed_x - 1.0*Accelerate_x*(Dt) == 0.0
18
+ Speed_y_dash - 1.0*Speed_y - 1.0*Accelerate_y*(Dt) == 0.0
19
+ ---
20
+ initials:
21
+ Location_x == 0.0
22
+ Location_y == 0.0
23
+ Speed_x == 0.0
24
+ Speed_y == 0.0
25
+ ---
26
+ instantaneous_constraints:
27
+ Location_x <= 10.0
28
+ Location_y <= 10.0
29
+ Location_x >= 0.0
30
+ Location_y >= 0.0
31
+ Accelerate_x <= 0.5
32
+ Accelerate_y <= 0.5
33
+ Accelerate_x >= -0.5
34
+ Accelerate_y >= -0.5
35
+ (Location_x <= 4.0) or (Location_x >= 6.0) or (Location_y <= 4.0) or (Location_y >= 6.0)
36
+ ---
37
+ temporal_constraints:
38
+ Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) <= 10.0
39
+ Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) <= 10.0
40
+ Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) >= 0.0
41
+ Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) >= 0.0
42
+
43
+ (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) <= 4.0) or (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) >= 6.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) <= 4.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) >= 6.0)
44
+ ---
45
+ goals:
46
+ Location_x == 8.0
47
+ Location_y == 8.0
48
+ ---
49
+ reward:
50
+ -1.0*(Dt)
@@ -0,0 +1,51 @@
1
+ constants:
2
+ Epsilon = config_epsilon
3
+ bigM = config_bigM
4
+ ---
5
+ pvariables:
6
+ action_continuous: Accelerate_x
7
+ action_continuous: Accelerate_y
8
+ action_continuous: Dt
9
+ state_continuous: Location_x
10
+ state_continuous: Location_y
11
+ state_continuous: Speed_x
12
+ state_continuous: Speed_y
13
+ ---
14
+ transitions:
15
+ Location_x_dash - 1.0*Location_x - 1.0*Speed_x*(Dt) - 0.5*Accelerate_x*(Dt)*(Dt) == 0.0
16
+ Location_y_dash - 1.0*Location_y - 1.0*Speed_y*(Dt) - 0.5*Accelerate_y*(Dt)*(Dt) == 0.0
17
+ Speed_x_dash - 1.0*Speed_x - 1.0*Accelerate_x*(Dt) == 0.0
18
+ Speed_y_dash - 1.0*Speed_y - 1.0*Accelerate_y*(Dt) == 0.0
19
+ ---
20
+ initials:
21
+ Location_x == 0.0
22
+ Location_y == 0.0
23
+ Speed_x == 0.0
24
+ Speed_y == 0.0
25
+ ---
26
+ instantaneous_constraints:
27
+ Location_x <= 10.0
28
+ Location_y <= 10.0
29
+ Location_x >= 0.0
30
+ Location_y >= 0.0
31
+ Accelerate_x <= 0.5
32
+ Accelerate_y <= 0.5
33
+ Accelerate_x >= -0.5
34
+ Accelerate_y >= -0.5
35
+ (Location_x <= 2.0) or (Location_x >= 4.0) or (Location_y <= 1.0) or (Location_y >= 5.0)
36
+ (Location_x <= 5.0) or (Location_x >= 7.0) or (Location_y <= 5.0) or (Location_y >= 9.0)
37
+ ---
38
+ temporal_constraints:
39
+ Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) <= 10.0
40
+ Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) <= 10.0
41
+ Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) >= 0.0
42
+ Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) >= 0.0
43
+ (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) <= 2.0) or (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) >= 4.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) <= 1.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) >= 5.0)
44
+ (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) <= 5.0) or (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) >= 7.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) <= 5.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) >= 9.0)
45
+ ---
46
+ goals:
47
+ Location_x == 8.0
48
+ Location_y == 8.0
49
+ ---
50
+ reward:
51
+ -1.0*(Dt)
@@ -0,0 +1,53 @@
1
+ constants:
2
+ Epsilon = config_epsilon
3
+ bigM = config_bigM
4
+ ---
5
+ pvariables:
6
+ action_continuous: Accelerate_x
7
+ action_continuous: Accelerate_y
8
+ action_continuous: Dt
9
+ state_continuous: Location_x
10
+ state_continuous: Location_y
11
+ state_continuous: Speed_x
12
+ state_continuous: Speed_y
13
+ ---
14
+ transitions:
15
+ Location_x_dash - 1.0*Location_x - 1.0*Speed_x*(Dt) - 0.5*Accelerate_x*(Dt)*(Dt) == 0.0
16
+ Location_y_dash - 1.0*Location_y - 1.0*Speed_y*(Dt) - 0.5*Accelerate_y*(Dt)*(Dt) == 0.0
17
+ Speed_x_dash - 1.0*Speed_x - 1.0*Accelerate_x*(Dt) == 0.0
18
+ Speed_y_dash - 1.0*Speed_y - 1.0*Accelerate_y*(Dt) == 0.0
19
+ ---
20
+ initials:
21
+ Location_x == 0.0
22
+ Location_y == 0.0
23
+ Speed_x == 0.0
24
+ Speed_y == 0.0
25
+ ---
26
+ instantaneous_constraints:
27
+ Location_x <= 10.0
28
+ Location_y <= 10.0
29
+ Location_x >= 0.0
30
+ Location_y >= 0.0
31
+ Accelerate_x <= 0.5
32
+ Accelerate_y <= 0.5
33
+ Accelerate_x >= -0.5
34
+ Accelerate_y >= -0.5
35
+ (Location_x <= 2.0) or (Location_x >= 4.0) or (Location_y <= 1.0) or (Location_y >= 9.0)
36
+ (Location_x <= 4.0) or (Location_x >= 7.0) or (Location_y <= 7.0) or (Location_y >= 9.0)
37
+ (Location_x <= 4.0) or (Location_x >= 9.0) or (Location_y <= 2.0) or (Location_y >= 6.0)
38
+ ---
39
+ temporal_constraints:
40
+ Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) <= 10.0
41
+ Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) <= 10.0
42
+ Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) >= 0.0
43
+ Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) >= 0.0
44
+ (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) <= 2.0) or (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) >= 4.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) <= 1.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) >= 9.0)
45
+ (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) <= 4.0) or (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) >= 7.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) <= 7.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) >= 9.0)
46
+ (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) <= 4.0) or (Location_x + Speed_x*(Dt) + 0.5*Accelerate_x*(Dt)*(Dt) >= 9.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) <= 2.0) or (Location_y + Speed_y*(Dt) + 0.5*Accelerate_y*(Dt)*(Dt) >= 6.0)
47
+ ---
48
+ goals:
49
+ Location_x == 8.0
50
+ Location_y == 8.0
51
+ ---
52
+ reward:
53
+ -1.0*(Dt)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scipplan
3
- Version: 0.1.1a0
3
+ Version: 0.2.0a1
4
4
  Summary: Metric Hybrid Factored Planning in Nonlinear Domains with Constraint Generation in Python.
5
5
  Author: Ari Gestetner, Buser Say
6
6
  Author-email: ari.gestetner@monash.edu, buser.say@monash.edu
@@ -16,6 +16,8 @@ Classifier: Programming Language :: Python :: 3
16
16
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
+ Requires-Dist: PySCIPOpt ==5.2.1
20
+ Requires-Dist: sympy ==1.13.3
19
21
 
20
22
  # SCIPPlan
21
23
 
@@ -121,17 +123,13 @@ state_continuous: Location_x
121
123
  state_continuous: Location_y
122
124
  state_continuous: Speed_x
123
125
  state_continuous: Speed_y
124
- global_boolean: aux_1
125
126
  ```
126
- where the variable and value type of the variable is set in the format "{variable type}_{value type}" and the variable itself has to be in a Python compatible format (e.g. variables can't use - symbol like `some-var` but can use _ like `some_var` as well as the dash sign ' cannot be used). The use of next state variables which is often written using the dash symbol will be explained further in the Transitions section.
127
+ where the variable and value type of the variable is set in the format "{variable type}_{value type}" and the variable itself has to be in a Python compatible format (e.g. variables can't use - sign like `some-var` but can use _ like `some_var` as well as the dash sign ' cannot be used). The use of next state variables which is often written using the dash symbol will be explained further in the Transitions section.
127
128
  Additionally a variable for Dt has to be defined and has to be the same as the dt_var in the config object so if you would like to use a different variable name for Dt (e.g. dt) please also ensure you add it to the config via the `--dt-var` tag or the `dt_var` parameter.
128
- The variable type `global` is used when you would like a non state variable to be equal over every time step over the horizon (e.g. if $v_t$ is a variable at time $t$ and $H$ is the horizon, then $v_1 = v_2 = \dots = v_{H+1}$).
129
-
130
129
  The available variable types are
131
130
  - state
132
131
  - action
133
132
  - auxiliary
134
- - global
135
133
 
136
134
  The available value types are
137
135
  - continuos
@@ -148,7 +146,7 @@ Location_y == 0.0
148
146
  Speed_x == 0.0
149
147
  Speed_y == 0.0
150
148
  ```
151
- notice the use of the constant value defined earlier in the constants file.
149
+ notice te use of teh constant value defined earlier in the constants file.
152
150
  ### Goals
153
151
  The goals file should encode the final state values such that t=H+1, for example
154
152
  ```txt
@@ -1,9 +1,9 @@
1
- scipplan/__init__.py,sha256=uKbPGbRV0K1aJ2e2_4MzHKuJxn36vtQ7yx5CqTL5Jsk,193
2
- scipplan/config.py,sha256=0D6UcLjrv4PTjYRiPoIYXAsRu4nwcaOIWnsI4lAdK6Y,5221
3
- scipplan/helpers.py,sha256=YwEr0NeDvb29_Ot686km3ZMJ-vHu-L8zjuexmlKDjpY,974
4
- scipplan/parse_model.py,sha256=CI_38xmaiVr8DuOi3UdNrVqWHTdW6qm_5luwLZxIk9I,11136
5
- scipplan/plan_model.py,sha256=Zr2NdoSTXkgqpnPVoNvGMjSyNDEJ2ql6_OYIQJGO_E0,11423
6
- scipplan/scipplan.py,sha256=z6cuRug4amCg6LU7S4RYHcV6uT3vWLHYGRh9OXFkKoU,8225
1
+ scipplan/__init__.py,sha256=RPBElHHcH17D6eKi9tgqPRYINNDEAAyBs3vJOkm8-xw,193
2
+ scipplan/config.py,sha256=Ojs_pdjhwRuANPJcGyb3m5mMGqbTZkHuNvppd_Wd4FQ,5615
3
+ scipplan/helpers.py,sha256=YmS0HPQymsO5_e3jK7WQ-hBRZnxoZtewLhuzubw5sR4,975
4
+ scipplan/parse_model.py,sha256=-vssLQZHbXxkoiHjTHD-ZxY2h0w9LvGuJZXSd4RZvlM,9564
5
+ scipplan/plan_model.py,sha256=iFbpZbSMNYjNxSpL7qW5ajQRGDY-ZAD3wVPaSjm-deo,14012
6
+ scipplan/scipplan.py,sha256=Ykz_L0f2dyX4-EQB1iCH-QR3waVUwxKzgskdQeUP9nE,8675
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
@@ -18,21 +18,27 @@ scipplan/translation/initials_navigation_3.txt,sha256=s7ukUEHwcmMsey1bHCRJh515PL
18
18
  scipplan/translation/instantaneous_constraints_navigation_1.txt,sha256=WbITeszv_n93_BhE2eiNqFPAZVO4f2s44KcKUsNURyA,244
19
19
  scipplan/translation/instantaneous_constraints_navigation_2.txt,sha256=e5YdZn3OKLJh0kEiCNqpOgxgAAQxIHMB3J5OTYvPlgw,333
20
20
  scipplan/translation/instantaneous_constraints_navigation_3.txt,sha256=HnzfFntGIQ0WIMnEfcYPg1cy7u9dJn3xuYqdXZVFFvE,422
21
+ scipplan/translation/odes_navigation_1.txt,sha256=Uv13eTSTvURb6TtY7rq-otlpJMS8cQDYSyaO3X2_SRs,1015
22
+ scipplan/translation/odes_navigation_2.txt,sha256=DcbpXv-q0NP8Tx10YKqD6425esblgPNlTxchkyWMJAc,1192
23
+ scipplan/translation/odes_navigation_3.txt,sha256=ZFTyFEiL1KP0yxOCOzOSoXz9dXulRmtXDBnfZqaVbaE,1370
21
24
  scipplan/translation/pvariables_navigation_1.txt,sha256=97t5uPWAWKmtbDPJZIor5nn5qPU6aMcGdpLAuKnlDbQ,217
22
25
  scipplan/translation/pvariables_navigation_2.txt,sha256=lGUNN04bC-CJFTThNC3dwP9kU2xGftSshx-24I6zlZw,216
23
26
  scipplan/translation/pvariables_navigation_3.txt,sha256=1-yvM5BSJ5TXBlHkMbcXWd5zoc2ezSBpIIuM_zwEXSo,216
24
27
  scipplan/translation/reward_navigation_1.txt,sha256=dvR0CkxkWRbO3wP0fenXDSDMpueEUtSUqw990UnCcJY,26
25
28
  scipplan/translation/reward_navigation_2.txt,sha256=ck6uUGNhM_DWiG1hHN6_xTps1muychzqTOpz1iLF9bk,26
26
29
  scipplan/translation/reward_navigation_3.txt,sha256=O8unFCIySCz4GCBX_9mQcm-JMn5Ur6upp3HBbA4e_C8,22
30
+ scipplan/translation/solutions_navigation_1.txt,sha256=5iLPRtJXqfAXi0QG-3WPtKn8t0pH4-E2AtNp8-7k1CQ,1542
31
+ scipplan/translation/solutions_navigation_2.txt,sha256=b1c74m54iRCcZoe8uqquUQyn6HtRTiFqIA8ss2mZUdg,1895
32
+ scipplan/translation/solutions_navigation_3.txt,sha256=Jv3bzMt84LVyR1DSVJ5B8Ky9id_khZ1PxZ1s3QPKpk8,2249
27
33
  scipplan/translation/temporal_constraints_navigation_1.txt,sha256=h06iRA5TDr6R5XdjhEyYnZ3f-FQwUkbKGNw-t0k0jm8,875
28
34
  scipplan/translation/temporal_constraints_navigation_2.txt,sha256=x73dbxxb_YzvdvtVNaJfG-S9ggf-yqTYdoU6NiDQBqk,1319
29
35
  scipplan/translation/temporal_constraints_navigation_3.txt,sha256=Ki4nAX9-QtBbY9ZdHwHdqta8JQoLrAVvlZrLa1pWLnQ,1668
30
36
  scipplan/translation/transitions_navigation_1.txt,sha256=kfnr3_A9mCfflLsL4aq7OeR_BHSNST6eYuAg4ZxaPoU,411
31
37
  scipplan/translation/transitions_navigation_2.txt,sha256=kfnr3_A9mCfflLsL4aq7OeR_BHSNST6eYuAg4ZxaPoU,411
32
38
  scipplan/translation/transitions_navigation_3.txt,sha256=aIPP3FOjXZ3G6sTqicEIZ0JKJxdxHCRRZIdc5bUPFBM,395
33
- scipplan-0.1.1a0.dist-info/LICENSE,sha256=tfR4peJA8KJtYEn1NzNV-LWQVRAserdq7OJgYghreR0,1057
34
- scipplan-0.1.1a0.dist-info/METADATA,sha256=QSfZ3QemoqT9M0GeUeBV4s5zdi5N5TozOt4iKQmqO8M,11498
35
- scipplan-0.1.1a0.dist-info/WHEEL,sha256=-G_t0oGuE7UD0DrSpVZnq1hHMBV9DD2XkS5v7XpmTnk,110
36
- scipplan-0.1.1a0.dist-info/entry_points.txt,sha256=3qiNbbp6qIwivyPmmikyp7ByCfmsa9rGFNJPcN9Is8I,52
37
- scipplan-0.1.1a0.dist-info/top_level.txt,sha256=xO2FLRn7YQ-C25E8lagIEbik5T5FTr-Ta5bdiZezEPY,9
38
- scipplan-0.1.1a0.dist-info/RECORD,,
39
+ scipplan-0.2.0a1.dist-info/LICENSE,sha256=tfR4peJA8KJtYEn1NzNV-LWQVRAserdq7OJgYghreR0,1057
40
+ scipplan-0.2.0a1.dist-info/METADATA,sha256=9mQSEmKgV45LuDGbyiV3H8IbEHQh0MKmjoyrsG068k4,11296
41
+ scipplan-0.2.0a1.dist-info/WHEEL,sha256=-G_t0oGuE7UD0DrSpVZnq1hHMBV9DD2XkS5v7XpmTnk,110
42
+ scipplan-0.2.0a1.dist-info/entry_points.txt,sha256=3qiNbbp6qIwivyPmmikyp7ByCfmsa9rGFNJPcN9Is8I,52
43
+ scipplan-0.2.0a1.dist-info/top_level.txt,sha256=xO2FLRn7YQ-C25E8lagIEbik5T5FTr-Ta5bdiZezEPY,9
44
+ scipplan-0.2.0a1.dist-info/RECORD,,