I don't know anything about Symfit, but if you're simply trying to generalize the above code to arbitrary N, then:
- You can arbitrarily generate a string that looks like
"p1, p2, p3"
for arbitrary N, and parse it into a list of parameters:
params_string = ", ".join("p{}".format(i + 1) for i in range(n))
params = parameters(params_string)
The notion of parsing a string to get a list of parameters sounds smelly to me, and I'm sure there's a nicer way to programatically declare a bunch of parameters, but this will be as close as possible to what your original code was doing.
EDIT: Looking at the Symfit documentation, it seems like parameters(s)
is just a shortcut, and you can actually just do:
params = [Parameter("p{}".format(i + 1)) for i in range(n)]
which doesn't require you to build your own joined string of all the parameter names just so Symfit can split them back into individual parameter names. This would also allow you to define other properties for your parameters, such as their initial values or their min/max bounds.
- You can generalize the
Eq
constraint:
coeffs = [xdata[0]] + [(xdata[i+1] - xdata[i]) for i in range(n-1)]
eq_constraint = Eq(sum(param * coeff for param, coeff in zip(params, coeffs), 1)
Or, as another answer does this, using numpy operations:
coeffs = np.concat(xdata[:1], np.diff(xdata))
eq_constraint = Eq(np.sum(params * coeffs), 1)
- You can generalize the
Ge
constraints:
ge_constraints = [Ge(params[i + 1], params[i]) for i in range(n - 1)] + [Ge(params[-1], 0]
constraints = [eq_constraint] + ge_constraints
Again this could be done using numpy operations, but I'll leave that to @user3483203's answer.
- You can multiply all the parameters using
reduce
:
model = reduce(lambda x, y: x * y, params, 1)
Or using numpy.prod
:
model = np.prod(params)
This should be enough to generalize the above to arbitrary N.