question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Binary function arbitrary for functions with various mathematical properties

See original GitHub issue

🚀 Feature Request / Motivation

I’ve been using fast-check’s fc.func(arb) and fc.compareFunc() arbitraries and they’ve been very useful because I frequently write functions that expect other functions as arguments!

However, sometimes I am testing a function that cannot accept any arbitrary function. Sometimes the function requires its input function to have certain mathematical properties. The ones I’ve run into most frequently are the following:

  • Commutativity/Symmetry: f(a, b) = f(b, a)
  • Associativity: f(f(a, b), c) = f(a, f(b, c))

Perhaps some new fc.binaryFunc(arb, { commutative: boolean, associative: boolean }) arbitrary could solve this problem.

Example

Using ava-fast-check:

import { testProp, fc } from 'ava-fast-check'

const foldInSomeOrder = (array, initial, fn) => {
  const copy = [...array]
  for (let i = n - 1; i >= 1; i--) {
    const j = Math.floor(Math.random() * (i + 1))
    ;[copy[i], copy[j]] = [copy[j], copy[i]]
  }

  return array.reduce((a, b) => fn(a, b), initial)
}

testProp(
  `foldInSomeOrder produces the same result as Array.prototype.reduce when the input function is commutative and associative`
  [fc.array(fc.anything()), fc.anything(), fc.func(fc.anything(), { commutative: true, associative: true })],
  (t, array, initial, fn) => {
    t.deepEqual(
      foldInSomeOrder(array, initial, fn),
      array.reduce((a, b) => fn(a, b), initial)
    )
  }
)

In this case the function must be both commutative and associative, but there are situations where they are not both required.

I have some ideas for how to implement this functionality so I’d be happy to make a PR if you think this would be useful.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:2
  • Comments:9 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
TomerAberbachcommented, Feb 20, 2021

At least for the commutative option, something like this is probably sufficient (assuming everything else is the same what you have for the current fc.func(arb) arbitrary):

const f = (a: T, b: T) => {
  const args = [stringify(a), stringify(b)]
  if (commutative) {
    args.sort()
  }
  const repr = stringify(args)
  const val = outs[hash(`${seed}${repr}`) % outs.length];
  recorded[repr] = val;
  return hasCloneMethod(val) ? val[cloneMethod]() : val;
};

I’m still trying to wrap my head around how you’d ensure associativity… I’ll let you know if I think of anything.

0reactions
dubzzzcommented, Mar 2, 2021

No, it passed fine. But I may have been lucky 😅

Read more comments on GitHub >

github_iconTop Results From Across the Web

Binary function - Wikipedia
A binary operation is a binary function where the sets X, Y, and Z are all equal; binary operations are often used to...
Read more >
Definition of a Binary Operation
A binary operation can be considered as a function whose input is two elements of the same set S S and whose output...
Read more >
Binary Function Symbol - an overview | ScienceDirect Topics
1. contains a binary function symbol f and a constant symbol e, and all other function symbols in are unary. 2. The symbol...
Read more >
Functional Operations - Wolfram Language Documentation
In this way, you can implement the mathematical properties of commutativity or symmetry for arbitrary functions. You can use Sort to put the...
Read more >
Binary Relations: Chapter 4.3 – 4.5 - MIT OpenCourseWare
and it plays an equally basic role in discrete mathematics. ... are four more standard properties of relations that come up all the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found