Skip to content

Instantly share code, notes, and snippets.

@SPY
Last active August 29, 2015 14:23
Show Gist options
  • Save SPY/547670b23bbc15eaab60 to your computer and use it in GitHub Desktop.
Save SPY/547670b23bbc15eaab60 to your computer and use it in GitHub Desktop.
5 6
2 -1
-5 3
9 2
4 6
5 -3
6 -2
-7 9
-6 9
5 4
import parseopt, strutils, math
type
Options = object
a, b, step: float
report: int
filename: string
DataPoint = tuple[x: float, y: float]
Data = seq[DataPoint]
proc readOpts(): Options =
var opts = new(Options)
opts.step = 0.01; opts.report = 1000
for kind, key, val in getopt():
case kind
of cmdArgument:
opts.filename = key.string
of cmdLongOption, cmdShortOption:
case key
of "a": opts.a = val.string.parseFloat()
of "b": opts.b = val.string.parseFloat()
of "step": opts.step = val.string.parseFloat()
of "report": opts.report = val.string.parseInt()
else: discard
of cmdEnd: assert(false)
opts[] # [] is dereference operator
proc `$`(opts: Options): string =
"filename: " & opts.filename &
" a: " & $opts.a &
" b: " & $opts.b &
" step: " & $opts.step &
" report: " & $opts.report
proc loadData(filename: string): Data =
result = newSeq[DataPoint]()
for line in lines(filename):
var parts = line.split(' ')
result.add((parts[0].parseFloat(), parts[1].parseFloat()))
echo "data loaded: " & $result.len & " points"
## calc derivate of mesure function in point (a,b) for data
proc dQ(data: Data, a, b: float): tuple[a, b: float] {. inline .} =
var
m = data.len().float()
sa, sb: float
for i in data:
sa += a + b*i.x - i.y
sb += (a + b*i.x - i.y)*i.x
(sa/m, sb/m)
## calc mesure function in point (a,b) for data
proc Q(data: Data, a: float, b: float): float {. inline .} =
let m = data.len().float()
for i in data:
result += pow(a + b*i.x - i.y, 2)
result /= 2.0 * m
proc calc(opts: Options) =
var
data = loadData(opts.filename)
a = opts.a
b = opts.b
prev = data.Q(a, b)
steps = 0
echo opts
while true:
inc(steps)
var
d = data.dQ(a, b)
newA = a - opts.step * d.a
newB = b - opts.step * d.b
newQ = data.Q(newA, newB)
if prev <= newQ:
break
a = newA; b = newB; prev = newQ
if steps mod opts.report == 0:
echo "Steps " & $steps & " a = " & $a & " b = " & $b
echo "Result. a = " & $a & " b = " & $b
readOpts().calc()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment