#! /usr/bin/python3 # Last edited on 2021-04-03 14:59:46 by jstolfi # Computes the combination of fertilizers to get # specified N-P-K amounts. import rn import rmxn import sys from math import sqrt, sin, cos, floor, ceil, exp, log, inf, nan, pi def main(): # Get the desired N,P,K amounts (grams) N = int(sys.argv[1]) P = int(sys.argv[2]) K = int(sys.argv[3]) b = [ N, P, K ] # Define the matrix of NPK contents and names of available fertilizers: M = [ [ 0.05, 0.15, 0.45 ], [ 0.30, 0.10, 0.10 ], [ 0.10, 0.54, 0.10 ], [ 0.45, 0.00, 0.00 ], ] Fname = [ "Plantafol 05-15-45", "Plantafol 30-10-10", "Plantafol 10-54-10", "Urea" ] # Solve the system obtaining the two extreme solutions: x0, x1 = solve43(M, b) sys.stderr.write("Raw solutions:\n") printsol(sys.stderr, x0, x1, M, Fname) # Trim the solution interval to positive amounts: x0, x1 = clipsol(x0, x1) sys.stderr.write("Clipped solutions:\n") printsol(sys.stderr, x0, x1, M, Fname) return 0 # ---------------------------------------------------------------------- def solve43(M, b): # Solves the system {x M = b} where {M} is 4 by 3, {x} is a 4-vector, # {b} is a 3-vector. assert len(M) == 4 assert len(b) == 3 # Solve using 0 of the last line: Q = M[0:3] Qinv = rmxn.inv_3(Q) x0 = rmxn.map_row(b, Qinv) x0 = x0 + [ 0, ] # Solve using 0 of the first line: P = M[1:] Pinv = rmxn.inv_3(P) x1 = rmxn.map_row(b, Pinv) x1 = [ 0, ] + x1 return x0, x1 # ---------------------------------------------------------------------- def clipsol(x0, x1): # Given two extreme solutions, clip the segment # to positive solutions: m = len(x0) assert len(x1) == m for k in range(m): if x0[k] < 0: r0 = -x0[k]/(x1[k]-x0[k]) x0 = rn.mix(1-r0, x0, r0, x1) if x1[k] < 0: r1 = -x1[k]/(x0[k]-x1[k]) x1 = rn.mix(1-r1, x1, r1, x0) return x0, x1 # ---------------------------------------------------------------------- def printsol(wr, x0, x1, M, Fname): # Prints the amounts of each fertilizer, in the two extreme formulations. m = len(x0) assert len(x1) == m assert len(Fname) == m for k in range(m): wr.write("%5.1f %5.1f %s\n" % (x0[k], x1[k], Fname[k])) # Check the solutions: v0 = rmxn.map_row(x0, M) v1 = rmxn.map_row(x1, M) for k in range(3): wr.write("%5.1f %5.1f %s\n" % (v0[k], v1[k], "NPK"[k])) return # ---------------------------------------------------------------------- main()