Finden der besten Kombination (pulp, scipy.optimize?)
Verfasst: Montag 27. April 2015, 21:19
Hallo,
Ich möchte eine Anzahl von (numpy-) Arrays gewichtet miteinander addieren und dadurch möglichst "nahe" an gegebene Zielwerte kommen.
Also mal als kleines Beispiel:
A1 * [0, 1, 1, 1] + A2 * [0, 0, 0, 4] + A3 * [0, 0, 2, 5] === [0, 1, 4, 4]
Die Faktoren A1, A2 und A3 dürfen nur Werte zwischen 0 und 1 annehmen. Ferner wird die Güte der Anpassung durch die Summe der Beträge der Differenzen an allen Punkten bestimmt.
An diesem Problem sitze ich nun schon wirklich lange und würde mich wirklich über Anregungen freuen-
Hier meine bisherigen Ansätze:
ILP-Problem mit pulp:
Dummerweise kann man in der Zielfunktion (condition) zwar Summen, aber keine Beträge verwenden...
Dann habe ich scipy.optimize.minimize versucht.
Ohne "Bounds" bekomme ich Lösungen für die Faktoren, jedoch sind die auch negativ. Wenn ich die "Bounds" angebe, wird keine Lösung mehr gefunden.
Herzlichen Dank!
Ich möchte eine Anzahl von (numpy-) Arrays gewichtet miteinander addieren und dadurch möglichst "nahe" an gegebene Zielwerte kommen.
Also mal als kleines Beispiel:
A1 * [0, 1, 1, 1] + A2 * [0, 0, 0, 4] + A3 * [0, 0, 2, 5] === [0, 1, 4, 4]
Die Faktoren A1, A2 und A3 dürfen nur Werte zwischen 0 und 1 annehmen. Ferner wird die Güte der Anpassung durch die Summe der Beträge der Differenzen an allen Punkten bestimmt.
An diesem Problem sitze ich nun schon wirklich lange und würde mich wirklich über Anregungen freuen-
Hier meine bisherigen Ansätze:
ILP-Problem mit pulp:
Code: Alles auswählen
ySoll = np.array([0., 1., 4., 4.])
yValues = np.array([[0, 1, 1, 1],
[0, 0, 0, 4],
[0, 0, 2, 5]
], float)
num = yValues.shape[0]
numYValues = yValues.shape[1]
A = []
for i in range(num):
A.append(LpVariable("A%s"%i, lowBound = 0, upBound = 1, cat= LpContinuous)) # amplitude variables
prob = LpProblem("combination", LpMinimize)
prob += lpSum([ySoll[j] - lpSum(A[i]*yValues[i][j] for i in range(num)) for j in range(numYValues)] )
for j in range(numYValues):
prob += lpSum(A[i]*yValues[i][j] for i in range(num)) == ySoll[j], "Equal_%s"%j
prob.writeLP("combinate.lp")
prob.solve()
print "Anpassung ", value(prob.objective)
resY = sum(A[i].varValue * yValues[i] for i in range(num))
print "Ziel: ", ySoll
print "Erreicht: ", resY
Dann habe ich scipy.optimize.minimize versucht.
Code: Alles auswählen
def peval(p, X):
return np.dot(X, p)
def objective(p, y, X):
return np.sum( np.fabs(y - peval(p, X)) )
#return np.sum( (y - peval(p, X)) ** 2 )
yValues = np.array([[0, 1, 4, 4],
[1, 0, 0, 4],
[4, 1, 1, 4],
[4, 1, 1, 4]
], float)
ySoll = np.array([0, 1, 4, 4])
p0 = np.zeros(4)
cons = {
'type': 'eq',
'fun': np.sum,
}
bnds = ((0, None), (0, None), (0, None), (0, None))
res = optimize.minimize(
objective, p0, args=(ySoll, yValues),
method='SLSQP', constraints=cons)
Herzlichen Dank!