Skip to content

Commit 743759f

Browse files
committed
[py] revised CtcInverse* contractors
1 parent 92a39b8 commit 743759f

11 files changed

Lines changed: 311 additions & 148 deletions

File tree

doc/manual/tuto/cp_robotics/lesson_c_dynamic_localization.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ State estimation with constraint programming
267267
:dedent: 0
268268

269269
**C.8.** **Fixpoint resolution.** Finally, the propagation loops need to be updated to incorporate the dynamic constraints.
270-
Note that the contractors :math:`\mathcal{C}_\mathbf{f}` and :math:`\mathcal{C}_{\mathrm{deriv}}` apply to the whole tubes :math:`[\mathbf{x}](\cdot)` and :math:`[\mathbf{v}](\cdot)`. Furthermore, the class ``CtcInverse`` can contract tubes using the ``.contract_tube(..)`` method, exactly as we would do for boxes. Finally, a *restriction* on a tube (*i.e.* setting a value to a slice) can be done using the ``.set(y,t)`` method, for setting the interval vector value ``y`` at time ``t``.
270+
Note that the contractors :math:`\mathcal{C}_\mathbf{f}` and :math:`\mathcal{C}_{\mathrm{deriv}}` apply to the whole tubes :math:`[\mathbf{x}](\cdot)` and :math:`[\mathbf{v}](\cdot)`. Furthermore, the class ``CtcInverse`` can contract tubes using the ``.contract(..)`` method, exactly as we would do for boxes. Finally, a *restriction* on a tube (*i.e.* setting a value to a slice) can be done using the ``.set(y,t)`` method, for setting the interval vector value ``y`` at time ``t``.
271271

272272
.. container:: toggle, toggle-hidden
273273

doc/manual/tuto/cp_robotics/src/lesson_C.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ int main()
191191
x.set(xi,yi[0]); // restriction on the tube x at time ti=yi[0]
192192
}
193193

194-
ctc_f.contract_tube(x,v);
194+
ctc_f.contract(x,v);
195195
ctc_deriv.contract(x,v);
196196

197197
}, x);

doc/manual/tuto/cp_robotics/src/lesson_C.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@
178178
x.set(xi,yi(1));
179179
end
180180

181-
res_ctc_f = ctc_f.contract_tube(x,v);
181+
res_ctc_f = ctc_f.contract(x,v);
182182
x = res_ctc_f{1};
183183
v = res_ctc_f{2};
184184

doc/manual/tuto/cp_robotics/src/lesson_C.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def ctc_all_obs(x):
170170
xi,yi,mi,ai,si = fixpoint(ctc_one_obs, xi,yi,mi,ai,si)
171171
x.set(xi,yi[0]) # restriction on the tube x at time ti=yi[0]
172172

173-
x,v = ctc_f.contract_tube(x,v)
173+
x,v = ctc_f.contract(x,v)
174174
ctc_deriv.contract(x,v)
175175

176176
return x

doc/manual/tuto/cp_robotics/src/lesson_D.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474

7575

7676
# [D-q7-beg]
77-
ctc_f.contract_tube(x,v)
77+
ctc_f.contract(x,v)
7878
ctc_deriv.contract(x,v)
7979
# [D-q7-end]
8080

@@ -120,7 +120,7 @@
120120
# [D-q13-beg]
121121
def contractors_list(x,v):
122122
ctc_deriv.contract(x,v)
123-
ctc_f.contract_tube(x,v)
123+
ctc_f.contract(x,v)
124124
for yi in Y: # for each range-only measurement
125125
ti = yi[1]
126126
pi = x(ti)

python/codac/core/__init__.py

Lines changed: 15 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from codac._core import *
99
import sys
10+
import warnings
1011

1112

1213
def codac_error(message):
@@ -120,116 +121,28 @@ def copy(self):
120121
return super().copy()
121122

122123

123-
class CtcInverse(Ctc_IntervalVector):
124-
125-
def __init__(self, f, y, with_centered_form=True):
126-
127-
f = AnalyticFunction(f)
128-
129-
if f.nb_args() > 1:
130-
total_var = VectorVar(f.input_size())
131-
132-
i = 0
133-
f_args = []
134-
for a in f.args():
135-
if a.size() == 1:
136-
f_args.append(total_var.get_item_0(i))
137-
i = i + 1
138-
else:
139-
f_args.append(total_var.subvector_0(i, i + a.size() - 1))
140-
i = i + a.size()
141-
142-
g = AnalyticFunction([total_var], f(*f_args))
143-
CtcInverse.__init__(self, g, y, with_centered_form)
144-
145-
else:
146-
Ctc_IntervalVector.__init__(self, f.input_size())
147-
if isinstance(f, AnalyticFunction_Scalar):
148-
if not (
149-
isinstance(y, (int, float, Interval))
150-
or (isinstance(y, list) and len(y) > 0 and len(y) <= 2 and isinstance(y[0], (int, float)))
151-
):
152-
codac_error("CtcInverse: inverse argument 'y' should be a scalar type (float,Interval)")
153-
self.c = CtcInverse_Interval(f, Interval(y), with_centered_form)
154-
elif isinstance(f, AnalyticFunction_Vector):
155-
if not isinstance(y, (Vector, IntervalVector, list, Ctc_IntervalVector, Ctc_IntervalVector_)):
156-
codac_error(
157-
"CtcInverse: inverse argument 'y' should be a vector type "
158-
"(Vector,IntervalVector,Ctc_IntervalVector,Ctc_IntervalVector_)"
159-
)
160-
if isinstance(y, (Ctc_IntervalVector, Ctc_IntervalVector_)):
161-
self.c = CtcInverse_IntervalVector(f, y, with_centered_form)
162-
else:
163-
self.c = CtcInverse_IntervalVector(f, IntervalVector(y), with_centered_form)
164-
else:
165-
codac_error("CtcInverse: can only build CtcInverse from scalar or vector functions")
166-
167-
def contract(self, *x):
168-
169-
if len(x) == 1:
170-
return self.c.contract(x[0])
171-
172-
total = cart_prod(*x)
173-
total = self.c.contract(total)
174-
i = 0
175-
for xi in x:
176-
k = xi.size()
177-
if k == 1:
178-
xi &= total.get_item_0(i)
179-
else:
180-
xi &= total.subvector_0(i, i + k - 1)
181-
i = i + k
182-
return x
183-
184-
def contract_tube(self, *x):
185-
186-
if len(x) == 1:
187-
return self.c.contract_tube(x[0])
188-
189-
total = tube_cart_prod(*x)
190-
total = self.c.contract_tube(total)
191-
i = 0
192-
for xi in x:
193-
k = xi.size()
194-
if k == 1:
195-
xi &= total.get_item_0(i)
196-
else:
197-
xi &= total.subvector_0(i, i + k - 1)
198-
i = i + k
199-
return x
124+
def CtcInverse(f, y, with_centered_form=True):
125+
f = AnalyticFunction(f)
200126

201-
def copy(self):
202-
return self.c.copy()
127+
if isinstance(f, AnalyticFunction_Scalar):
128+
return CtcInverse_Interval(f, y, with_centered_form)
203129

204-
def fnc(self):
205-
return self.c.fnc()
130+
if isinstance(f, AnalyticFunction_Vector):
131+
return CtcInverse_IntervalVector(f, y, with_centered_form)
206132

133+
codac_error("CtcInverse: can only build CtcInverse from scalar or vector functions")
207134

208-
class CtcInverseNotIn(Ctc_IntervalVector):
209135

210-
def __init__(self, f, y, with_centered_form=True):
211-
f = AnalyticFunction(f)
136+
def CtcInverseNotIn(f, y, with_centered_form=True):
137+
f = AnalyticFunction(f)
212138

213-
Ctc_IntervalVector.__init__(self, f.input_size())
214-
if isinstance(f, AnalyticFunction_Scalar):
215-
if not (
216-
isinstance(y, (int, float, Interval))
217-
or (isinstance(y, list) and len(y) > 0 and len(y) <= 2 and isinstance(y[0], (int, float)))
218-
):
219-
codac_error("CtcInverseNotIn: inverse argument 'y' should be a scalar type (float,Interval)")
220-
self.c = CtcInverseNotIn_Interval(f, Interval(y), with_centered_form)
221-
elif isinstance(f, AnalyticFunction_Vector):
222-
if not isinstance(y, (Vector, IntervalVector, list)):
223-
codac_error("CtcInverseNotIn: inverse argument 'y' should be a vector type (Vector,IntervalVector)")
224-
self.c = CtcInverseNotIn_IntervalVector(f, IntervalVector(y), with_centered_form)
225-
else:
226-
codac_error("CtcInverseNotIn: can only build CtcInverseNotIn from scalar or vector functions")
139+
if isinstance(f, AnalyticFunction_Scalar):
140+
return CtcInverseNotIn_Interval(f, y, with_centered_form)
227141

228-
def contract(self, x):
229-
return self.c.contract(x)
142+
if isinstance(f, AnalyticFunction_Vector):
143+
return CtcInverseNotIn_IntervalVector(f, y, with_centered_form)
230144

231-
def copy(self):
232-
return self.c.copy()
145+
codac_error("CtcInverseNotIn: can only build CtcInverseNotIn from scalar or vector functions")
233146

234147

235148
def Approx(x, eps=sys.float_info.epsilon*10):

python/src/core/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
contractors/codac2_py_CtcIdentity.cpp
2727
contractors/codac2_py_CtcInter.cpp
2828
contractors/codac2_py_CtcInverse.h
29-
contractors/codac2_py_CtcInverseNotIn.h
3029
contractors/codac2_py_CtcLazy.cpp
3130
contractors/codac2_py_CtcLohner.cpp
3231
contractors/codac2_py_CtcNot.cpp

python/src/core/codac2_py_core.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "codac2_py_Sep.h"
2020
#include "codac2_py_AnalyticFunction.h"
2121
#include "codac2_py_CtcInverse.h"
22-
#include "codac2_py_CtcInverseNotIn.h"
2322
#include "codac2_py_MatrixBlock.h"
2423
#include "codac2_py_Slice.h"
2524

@@ -193,10 +192,12 @@ PYBIND11_MODULE(_core, m)
193192
export_CtcIdentity(m, py_ctc_iv);
194193
export_CtcInnerOuter(m, py_ctc_iv);
195194
export_CtcInter(m, py_ctc_iv);
196-
export_CtcInverse<ScalarType>(m,"CtcInverse_Interval",py_ctc_iv);
197-
export_CtcInverse<VectorType>(m,"CtcInverse_IntervalVector",py_ctc_iv);
198-
export_CtcInverseNotIn<ScalarType>(m,"CtcInverseNotIn_Interval",py_ctc_iv);
199-
export_CtcInverseNotIn<VectorType>(m,"CtcInverseNotIn_IntervalVector",py_ctc_iv);
195+
196+
export_CtcInverse<CtcInverse<Interval>>(m,"CtcInverse_Interval",py_ctc_iv);
197+
export_CtcInverse<CtcInverse<IntervalVector>>(m,"CtcInverse_IntervalVector",py_ctc_iv);
198+
export_CtcInverse<CtcInverseNotIn<Interval>>(m,"CtcInverseNotIn_Interval",py_ctc_iv);
199+
export_CtcInverse<CtcInverseNotIn<IntervalVector>>(m,"CtcInverseNotIn_IntervalVector",py_ctc_iv);
200+
200201
export_CtcLazy(m, py_ctc_iv);
201202
export_CtcLohner(m);
202203
export_CtcNot(m, py_ctc_iv);

python/src/core/contractors/codac2_py_Ctc.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,38 @@ namespace py = pybind11;
2222
using namespace py::literals;
2323

2424

25+
template<typename C>
26+
const CtcBase<IntervalVector>& as_ctc_base(const C& c)
27+
{
28+
static_assert(std::is_base_of_v<CtcBase<IntervalVector>, C>,
29+
"bind_contract_overloads requires C to derive from CtcBase<IntervalVector>");
30+
return static_cast<const CtcBase<IntervalVector>&>(c);
31+
}
32+
33+
#define CONTRACT_METHODS(exp,clss,doc) \
34+
exp \
35+
.def("contract", \
36+
[](const clss& c, IntervalVector& x) -> const IntervalVector& \
37+
{ as_ctc_base<clss>(c).contract(x); return x; }, \
38+
doc, "x"_a) \
39+
.def("contract", \
40+
[](const clss& c, SlicedTube<IntervalVector>& x) -> const SlicedTube<IntervalVector>& \
41+
{ as_ctc_base<clss>(c).contract(x); return x; }, \
42+
doc, "x"_a) \
43+
/* Deprecated: */ \
44+
.def("contract_tube", \
45+
[](const clss& c, SlicedTube<IntervalVector>& x) -> const SlicedTube<IntervalVector>& \
46+
{ \
47+
std::cout << "CtcInverse.contract_tube(...) is deprecated; use CtcInverse.contract(...) with SlicedTube arguments instead" << std::endl; \
48+
as_ctc_base<clss>(c).contract(x); return x; \
49+
}, \
50+
doc, "x"_a) \
51+
; \
52+
2553
#define CONTRACT_BOX_METHOD(clss,doc) \
2654
"contract", [](const clss& c, IntervalVector& x) -> const IntervalVector& { c.contract(x); return x; }, doc, "x"_a
2755

56+
2857
class pyCtcIntervalVector : public CtcBase<IntervalVector>
2958
{
3059
public:

0 commit comments

Comments
 (0)