Esempio n. 1
0
 def get_variables(self, child=None, name=None, **kwargs):
     if child is None:
         return self._var_result
     elif name is None:
         return self._var_result.prefix(child.label)
     else:
         if name in child._substitutes:
             if name in child._splines_prim and not ('spline' in kwargs and
                                                     not kwargs['spline']):
                 basis = child._splines_prim[name]['basis']
                 if 'symbolic' in kwargs and kwargs['symbolic']:
                     if 'substitute' in kwargs and not kwargs['substitute']:
                         coeffs = child._substitutes[name][1]
                     else:
                         coeffs = child._substitutes[name][0]
                 else:
                     fun = self.substitutes[child][name]
                     coeffs = np.array(
                         fun(self._var_result, self._par_result))
                 return [
                     BSpline(basis, coeffs[:, k])
                     for k in range(coeffs.shape[1])
                 ]
             else:
                 if 'symbolic' in kwargs and kwargs['symbolic']:
                     if 'substitute' in kwargs and not kwargs['substitute']:
                         return child._substitutes[name][1]
                     else:
                         return child._substitutes[name][0]
                 else:
                     fun = self.substitutes[child][name]
                     return np.array(fun(self._var_result,
                                         self._par_result))
         if name in child._splines_prim and not ('spline' in kwargs
                                                 and not kwargs['spline']):
             basis = child._splines_prim[name]['basis']
             if 'symbolic' in kwargs and kwargs['symbolic']:
                 coeffs = child._variables[name]
             else:
                 coeffs = np.array(self._var_result[child.label, name])
             return [
                 BSpline(basis, coeffs[:, k])
                 for k in range(coeffs.shape[1])
             ]
         else:
             if 'symbolic' in kwargs and kwargs['symbolic']:
                 return child._variables[name]
             else:
                 return np.array(self._var_result[child.label, name])
Esempio n. 2
0
 def define_substitute(self, name, expr):
     if isinstance(expr, list):
         return [
             self.define_substitute(name + str(l), e)
             for l, e in enumerate(expr)
         ]
     else:
         if name in self._substitutes:
             raise ValueError('Name %s already used for substitutes!' %
                              (name))
         symbol_name = self._add_label(name)
         if isinstance(expr, BSpline):
             self._splines_prim[name] = {'basis': expr.basis}
             coeffs = MX.sym(symbol_name, expr.coeffs.shape[0], 1)
             subst = BSpline(expr.basis, coeffs)
             self._substitutes[name] = [expr.coeffs, subst.coeffs]
             inp_sym, inp_num = [], []
             for sym in symvar(expr.coeffs):
                 inp_sym.append(sym)
                 inp_num.append(
                     DM(self._values[self.symbol_dict[sym.name()][1]]))
             fun = Function('eval', inp_sym, [expr.coeffs])
             self._values[name] = fun(*inp_num)
             self.add_to_dict(coeffs, name)
         else:
             subst = MX.sym(symbol_name, expr.shape[0], expr.shape[1])
             self._substitutes[name] = [expr, subst]
             self.add_to_dict(subst, name)
         return subst
Esempio n. 3
0
def crop_spline(spline, min_value, max_value):
    T, knots2 = get_interval_T(spline.basis, min_value, max_value)
    if isinstance(spline.coeffs, (SX, MX)):
        coeffs2 = mtimes(T, spline.coeffs)
    else:
        coeffs2 = T.dot(spline.coeffs)
    basis2 = BSplineBasis(knots2, spline.basis.degree)
    return BSpline(basis2, coeffs2)
    def _define_mx_spline(self, name, size0, size1, dictionary, basis, value=None):
        if size1 > 1:
            return [self._define_mx_spline(name+str(l), size0,
                                           1, dictionary, basis, value)
                    for l in range(size1)]
        else:

            coeffs = self._define_mx(
                name, len(basis), size0, dictionary, value)
            self._splines_prim[name] = {'basis': basis}
            return [BSpline(basis, coeffs[:, k]) for k in range(size0)]
Esempio n. 5
0
def concat_splines(segments, segment_times):
    spl0 = segments[0]
    knots = [s.basis.knots*segment_times[0] for s in spl0]
    degree = [s.basis.degree for s in spl0]
    coeffs = [s.coeffs for s in spl0]
    for k in range(1, len(segments)):
        for l, s in enumerate(segments[k]):
            if s.basis.degree != degree[l]:
                raise ValueError(
                    'Splines at index ' + l + 'should have same degree.')
            knots[l] = np.r_[
                knots[l], s.basis.knots[degree[l]+1:]*segment_times[k] + knots[l][-1]]
            coeffs[l] = np.r_[coeffs[l], s.coeffs]
    bases = [BSplineBasis(knots[l], degree[l])
             for l in range(len(segments[0]))]
    return [BSpline(bases[l], coeffs[l]) for l in range(len(segments[0]))]
 def get_parameters(self, child=None, name=None, **kwargs):
     if child is None:
         return self._par_result
     elif name is None:
         return self._par_result.prefix(child.label)
     else:
         if name in child._splines_prim and not ('spline' in kwargs and not kwargs['spline']):
             basis = child._splines_prim[name]['basis']
             if 'symbolic' in kwargs and kwargs['symbolic']:
                 coeffs = child._parameters[name]
             else:
                 coeffs = np.array(self._par_result[child.label, name])
             return [BSpline(basis, coeffs[:, k]) for k in range(coeffs.shape[1])]
         else:
             if 'symbolic' in kwargs and kwargs['symbolic']:
                 return child._parameters[name]
             else:
                 return np.array(self._par_result[child.label, name])
Esempio n. 7
0
def running_integral(spline):
    # Compute running integral from spline
    basis = spline.basis
    coeffs = spline.coeffs
    knots = basis.knots
    degree = basis.degree

    knots_int = np.r_[knots[0], knots, knots[-1]]
    degree_int = degree + 1
    basis_int = BSplineBasis(knots_int, degree_int)
    coeffs_int = [0.]
    for i in range(len(basis_int)-1):
        coeffs_int.append(coeffs_int[i]+(knots[degree+i+1]-knots[i])/float(degree_int)*coeffs[i])
    if isinstance(coeffs, (MX, SX)):
        coeffs_int = vertcat(*coeffs_int)
    else:
        coeffs_int = np.array(coeffs_int)
    spline_int = BSpline(basis_int, coeffs_int)
    return spline_int
def concat_splines(segments, segment_times, n_insert=None):
    # While concatenating check continuity of segments, this determines
    # the required amount of knots to insert. If segments are continuous
    # up to degree, no extra knots are required. If they are not continuous
    # at all, degree+1 knots are inserted in between the splines.
    spl0 = segments[0]
    knots = [s.basis.knots * segment_times[0] for s in spl0]  # give dimensions
    degree = [s.basis.degree for s in spl0]
    coeffs = [s.coeffs for s in spl0]
    prev_segment = [s.scale(segment_times[0], shift=0) for s in spl0
                    ]  # save the combined segment until now (with dimenions)
    prev_time = segment_times[0]  # save the motion time of combined segment
    for k in range(1, len(segments)):
        for l, s in enumerate(segments[k]):
            if s.basis.degree != degree[l]:
                # all concatenated splines should be of the same degree
                raise ValueError('Splines at index ' + l +
                                 'should have same degree.')
            if n_insert is None:
                # check continuity, n_insert can be different for each l
                n_insert = degree[l] + 1  # starts at max value
                for d in range(degree[l] + 1):
                    # use ipopt default tolerance as a treshold for check (1e-3)
                    # give dimensions, to compare using the same time scale
                    # use scale function to give segments[k][l] dimensions
                    # prev_segment already has dimensions

                    # Todo: sometimes this check fails, or you get 1e-10 and 1e-11 values that should actually be equal
                    # this seems due to the finite tolerance of ipopt? and due to the fact that these are floating point numbers
                    val1 = segments[k][l].scale(
                        segment_times[k],
                        shift=prev_time).derivative(d)(prev_time)
                    val2 = prev_segment[l].derivative(d)(prev_time)
                    if (abs(val1 - val2) * 0.5 / (val1 + val2) <= 1e-3):
                        # more continuity = insert less knots
                        n_insert -= 1
                    else:
                        # spline values were not equal, stop comparing and use latest n_insert value
                        break
            # else:  # keep n_insert from input

            if n_insert != degree[l] + 1:
                # concatenation requires re-computing the coefficients and/or adding extra knots
                # here we make the knot vector and coeffs of the total spline (the final output),
                # but we also compute the knot vector and coeffs for concatenating just two splines,
                # to limit the size of the system that we need to solve
                # i.e.: when concatenating 3 splines, we first concatenate segments 1 and 2,
                # and afterwards segments 2 and 3, this happens due to the main for loop

                # make total knot vector
                end_idx = len(knots[l]) - (degree[l] + 1) + n_insert
                knots[l] = np.r_[knots[l][:end_idx],
                                 s.basis.knots[degree[l] + 1:] *
                                 segment_times[k] +
                                 knots[l][-1]]  # last term = time shift

                # make knot vector for two segments to concatenate
                end_idx_concat = len(
                    prev_segment[l].basis.knots) - (degree[l] + 1) + n_insert
                knots1 = prev_segment[l].basis.knots[:end_idx_concat]
                knots2 = s.basis.knots[degree[l] +
                                       1:] * segment_times[k] + knots1[
                                           -1]  # last term = time shift
                knots_concat = np.r_[knots1, knots2]

                # make union basis for two segments to concatenate
                basis_concat = BSplineBasis(knots_concat, degree[l])
                grev_bc = basis_concat.greville()
                # shift first and last greville point inwards, to avoid numerical problems,
                # in which the spline evaluates to 0 because the evaluation lies just outside the domain
                grev_bc[0] = grev_bc[0] + (grev_bc[1] - grev_bc[0]) * 0.01
                grev_bc[-1] = grev_bc[-1] - (grev_bc[-1] - grev_bc[-2]) * 0.01
                # evaluate basis on its greville points
                eval_bc = basis_concat(grev_bc).toarray()

                # only the last degree coeffs of segment1 and the first degree coeffs
                # of segment2 will change --> we can reduce the size of the system to solve
                # Todo: implement this reduction

                # first give the segment dimensions, by scaling it and shifting it appropriatly
                # this is necessary, since by default the domain is [0,1]
                # then evaluate the splines that you want to concatenate on greville points
                # of union basis, will give 0 outside their domain
                s_1 = prev_segment[l](grev_bc)
                s_2 = segments[k][l].scale(segment_times[k],
                                           shift=prev_time)(grev_bc)
                # sum to get total evaluation
                eval_sc = s_1 + s_2

                # solve system to find new coeffs
                coeffs_concat = la.solve(eval_bc, eval_sc)
                # save new coefficients
                coeffs[l] = coeffs_concat
            else:
                #there was no continuity, just compute new knot vector and stack coefficients
                knots[l] = np.r_[knots[l], s.basis.knots[degree[l] + 1:] *
                                 segment_times[k] + knots[l][-1]]
                coeffs[l] = np.r_[coeffs[l], s.coeffs]
        # going to next segment, update time shift
        new_bases = [
            BSplineBasis(knots[l], degree[l]) for l in range(len(segments[0]))
        ]
        prev_segment = [
            BSpline(new_bases[l], coeffs[l]) for l in range(len(segments[0]))
        ]
        prev_time += segment_times[k]

    bases = [
        BSplineBasis(knots[l], degree[l]) for l in range(len(segments[0]))
    ]
    return [BSpline(bases[l], coeffs[l]) for l in range(len(segments[0]))]