a simple fuzzy.e

new topic     » topic index » view thread      » older message » newer message

Here's a simple fuzzy.e which may be useful. You can make fuzzy()
act as =, <, >, !=, >=, or <=, depending on the operation you tell it
to do. fuzzy_compare() acts just like compare(), except that it will
do fuzzy comparisons.

jbrown

--CUT HERE--
with trace
-- fuzzy.e
-- function for fuzzy comparisions
-- sorry, very little testing

--define the ops
global constant OP_EQ = 1, OP_NEQ = 2, OP_GR = 3, OP_LS = 4,
				OP_GE = 5, OP_LE = 6

--heres the range which numbers are considered equal - must be a pos
value
global atom fuzzy_diff fuzzy_diff = 0.0000001

--fuzzy for atoms
global function fuzzy_atom(atom a1, integer op, atom a2)
	atom diff
	diff = fuzzy_diff
	if 0 then
	elsif op = OP_EQ then
		--original algorithem
		--if the difference in the numbers is between diff and -diff
		--(with 0 being the most ideal) they can be conidered equal
		return ((a1-a2) < diff) and ((a1-a2) > -diff)
	elsif op = OP_NEQ then
		--simply perform logical not on equal test
		return not fuzzy_atom(a1, OP_EQ, a2)
	elsif op = OP_GR then
		if fuzzy_atom(a1, OP_EQ, a2) then
			--make sure that they're not equal first!
			return 0
		end if
		--if a1 is more, diff is positive
		return (a1-a2) > 0
	elsif op = OP_LS then
		if fuzzy_atom(a1, OP_EQ, a2) then
			--make sure that they're not equal first!
			return 0
		end if
		--if a1 is less, diff is negative
		return (a1-a2) < 0
	elsif op = OP_GE then
		if fuzzy_atom(a1, OP_EQ, a2) then
			--test for equalness first
			return 1
		end if
		--test a1 > a2
		return fuzzy_atom(a1, OP_GR, a2)
	elsif op = OP_LE then
		if fuzzy_atom(a1, OP_EQ, a2) then
			--test for equalness first
			return 1
		end if
		--test a1 < a2
		return fuzzy_atom(a1, OP_LS, a2)
	end if
end function

--main fuzzy function
global function fuzzy(object a1, integer op, object a2)
	if atom(a1) and atom(a2) then
		return fuzzy_atom(a1, op, a2)
	elsif atom(a1) or atom(a2) then
		--abort
		? a1 = a2
	end if
	if length(a1) != length(a2) then
		--abort
		? a1 = a2
	end if
	for i = 1 to length(a1) do
		a1[i] = fuzzy(a1[i], op, a2[i])
	end for
	return a1
end function

--fuzzy version of compare
global function fuzzy_compare(object a1, object a2)
	integer r
	integer l, g
	sequence a
	if atom(a1) and atom(a2) then
		if fuzzy_atom(a1, OP_EQ, a2) then
			return 0
		elsif fuzzy_atom(a1, OP_GR, a2) then
			return 1
		else --fuzzy_atom(a1, OP_LS, a2) - must be this, no need to check
			return -1
		end if
	elsif atom(a1) or atom(a2) then
		--sequence always larger than atom
		--its safe to use compare here
		return compare(a1, a2)
	end if
	--get the size of the smaller sequence - can't compare beyond there
	if length(a1) > length(a2) then
		r = length(a2)
	else
		r = length(a1)
	end if
	a = repeat(0, r)
	for i = 1 to r do
		a[i] = fuzzy_compare(a1[i], a2[i])
	end for
	g = find(1, a)
	l = find(-1, a)
	if g = 0 and l = 0 then
		if length(a1) = length(a2) then
			return 0
		elsif length(a1) > length(a2) then
			return 1
		else --length(a1) < length(a2) - no need to check
			return -1
		end if
	elsif g = 0 then
		return 1
	elsif l = 0 then
		return -1
	else
		if g > l then
			--greater comparision was first
			return 1
		else
			--greater comparision was not first
			return 0
		end if
	end if
end function

--a simple test
atom az
az = 0
for i = 1 to 10 do
	az += .1 --az ~= 1
end for

--compare eu compare op with fuzzy()
? {az} = {1}
? fuzzy({az}, OP_EQ, {1})

--compare eu compare() with fuzzy_compare()
? compare({az}, {1}) = 0
? fuzzy_compare({az}, {1}) = 0
--CUT HERE--

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu