timfuz: linprog write output csv

Signed-off-by: John McMaster <johndmcmaster@gmail.com>
This commit is contained in:
John McMaster 2018-08-29 14:27:57 -07:00
parent 5ecbd135ce
commit e83866af72
2 changed files with 75 additions and 5 deletions

View File

@ -111,6 +111,36 @@ def run_corner(Anp, b, names, verbose=False, opts={}, meta={}, outfn=None):
print('Writing %s' % fn_out)
np.save(fn_out, (3, c, A_ub, b_ub, bounds, names, res, meta))
if outfn:
# ballpark minimum actual observed delay is around 7 (carry chain)
# anything less than one is probably a solver artifact
delta = 0.5
print('Writing resutls')
skips = 0
with open(outfn, 'w') as fout:
# write as one variable per line
# this natively forms a bound if fed into linprog solver
fout.write('ico,fast_max fast_min slow_max slow_min,rows...\n')
for xval, name in zip(res.x, names):
row_ico = 1
# FIXME: only report for the given corner?
# also review ceil vs floor choice for min vs max
# lets be more conservative for now
if xval < delta:
#print('Skipping %s: %0.6f' % (name, xval))
skips += 1
continue
#xvali = round(xval)
xvali = math.ceil(xval)
corners = [xvali for _ in range(4)]
items = [str(row_ico), ' '.join([str(x) for x in corners])]
items.append('%u %s' % (1, name))
fout.write(','.join(items) + '\n')
print('Wrote: skip %u => %u / %u valid delays' % (skips, len(names) - skips, len(names)))
def main():
import argparse
@ -121,6 +151,7 @@ def main():
parser.add_argument('--verbose', action='store_true', help='')
parser.add_argument('--massage', action='store_true', help='')
parser.add_argument('--sub-csv', help='')
parser.add_argument('--sub-json', help='Group substitutions to make fully ranked')
parser.add_argument('--corner', default="slow_max", help='')
parser.add_argument('--out', default=None, help='output timing delay .json')
@ -141,7 +172,7 @@ def main():
sub_json = load_sub(args.sub_json)
try:
timfuz_solve.run(run_corner=run_corner, sub_json=sub_json,
timfuz_solve.run(run_corner=run_corner, sub_json=sub_json, sub_csv=args.sub_csv,
fns_in=fns_in, corner=args.corner, massage=args.massage, outfn=args.out, verbose=args.verbose)
finally:
print('Exiting after %s' % bench)

View File

@ -36,7 +36,7 @@ def check_feasible(A_ub, b_ub):
Delays should be in order of ns, so a 10 ns delay should be way above what anything should be
Series can have several hundred delay elements
Max delay in ballpark
'''
'''
xs = [1e9 for _i in range(cols)]
# FIXME: use the correct np function to do this for me
@ -74,7 +74,29 @@ def instances(Ads):
ret += sum(row_ds.values())
return ret
def run(fns_in, corner, run_corner, sub_json=None, dedup=True, massage=False, outfn=None, verbose=False, **kwargs):
def Ads2bounds(Ads, b):
ret = {}
for row_ds, row_b in zip(Ads, b):
assert len(row_ds) == 1
k, v = list(row_ds.items())[0]
assert v == 1
ret[k] = row_b
return ret
def filter_bounds(Ads, b, bounds):
'''Given min variable delays, remove rows that won't constrain solution'''
ret_Ads = []
ret_b = []
for row_ds, row_b in zip(Ads, b):
# some variables get estimated at 0
est = sum([bounds.get(k, 0) * v for k, v in row_ds.items()])
# will this row potentially constrain us more?
if row_b > est:
ret_Ads.append(row_ds)
ret_b.append(row_b)
return ret_Ads, ret_b
def run(fns_in, corner, run_corner, sub_json=None, sub_csv=None, dedup=True, massage=False, outfn=None, verbose=False, **kwargs):
print('Loading data')
Ads, b = loadc_Ads_b(fns_in, corner, ico=True)
@ -87,7 +109,7 @@ def run(fns_in, corner, run_corner, sub_json=None, dedup=True, massage=False, ou
Ads, b = simplify_rows(Ads, b)
print('Simplify %u => %u rows' % (oldn, len(Ads)))
print('Simplify %u => %u instances' % (iold, instances(Ads)))
if sub_json:
print('Sub: %u rows' % len(Ads))
iold = instances(Ads)
@ -99,6 +121,23 @@ def run(fns_in, corner, run_corner, sub_json=None, dedup=True, massage=False, ou
else:
names = index_names(Ads)
# post substitution csv
# actually this might not be strictly necessary since subs would just not apply
# however, I wanted to do some filtering based on expected form
if sub_csv:
Ads2, b2 = loadc_Ads_b([sub_csv], corner, ico=True)
if 0:
Ads = Ads + Ads2
b = b + b2
else:
bounds = Ads2bounds(Ads2, b2)
rows_old = len(Ads)
Ads, b = filter_bounds(Ads, b, bounds)
print('Filter bounds: %s => %s rows' % (rows_old, len(Ads)))
if 1:
Ads = Ads + Ads2
b = b + b2
if verbose:
print
print_eqns(Ads, b, verbose=verbose)
@ -115,7 +154,7 @@ def run(fns_in, corner, run_corner, sub_json=None, dedup=True, massage=False, ou
However, a better solution is something like
a = 10
b = 90
This creates derived constraints to provide more realistic results
This creates derived constraints to provide more realistic results
'''
if massage:
Ads, b = massage_equations(Ads, b)