Loading [MathJax]/jax/output/HTML-CSS/jax.js

First time here? Check out the FAQ!

Ask Your Question
1

Set-Intersection Iteration

asked 4 years ago

u220e gravatar image

updated 4 years ago

Suppose I have two sets with integral elements A = {a1,a2,...,an} and B = {b1,b2,...,bm}, the cardinalities of which are arbitrarily large, and an>an1>an2>...>a1 and bm>bm1>bm2>...>b1 with nm. Suppose, also, that the intersection of sets A and B is the singleton set {c}, and there exists an index i such that bi+1>an>bi>bi1>...>b1 where an=sup(A).

I want to create a for-loop iteration (or whatever the best approach might be!) that finds the set intersection without generating all the elements of both sets and then determining the set {c}. (This is possible because the generating functions I've created yield explicit formulas I can use to calculate specific elements of both sets.)

I wrote some basic code in Sage to calculate elementary set intersection, but for even moderately large cardinalities, the halt time was incredibly long. I'm thinking the following approach might be faster, but I don't know how to write the program using for-/while-loops and if/else constructions (or even if I should do so):

(1) Check if an1bi. If an1>bi, keep checking conterminous decreasing indices for elements of A (i.e., an2, an3, etc.) until ajbi for some index j<n1. If aj=bi, break and print(aj). If not, go to step (2).

(2) When aj<bi, check conterminous decreasing indices for elements of B (i.e., bi1, bi2, etc.) until ajbk for some index k<i. If aj=bk, break and print(bk). If not, go to step (3).

(3) Repeat the process in steps (1) and (2) until ar=bs for some indices rs; then, break and print(bs).

Thanks in advance.

Preview: (hide)

Comments

Yes, you could do that using "iterators" that produce elements in increasing order one by one.

FrédéricC gravatar imageFrédéricC ( 4 years ago )

Great. Could you point me to a site/book that will show me how to write this kind of iterative code? The tutorials I've read only show basic for- or while-loop constructions with one or two nested if-then conditions.

u220e gravatar imageu220e ( 4 years ago )

In the question you write:

I wrote some basic code in Sage to calculate elementary set intersection, but for even moderately large cardinalities, the halt time was incredibly long.

Please provide the code you wrote so far and we can help build from that.

slelievre gravatar imageslelievre ( 4 years ago )

To display blocks of code or error messages in Ask Sage, skip a line above and below, and do one of the following (all give the same result):

  • indent all code lines with 4 spaces
  • select all code lines and click the "code" button (the icon with '101 010')
  • select all code lines and hit ctrl-K

For instance, typing

If we define `f` by

    def f(x, y, z):
        return x * y * z

then `f(2, 3, 5)` returns `30` but `f(2*3*5)` gives:

    TypeError: f() takes exactly 3 arguments (1 given)

produces:

If we define f by

def f(x, y, z):
    return x * y * z

then f(2, 3, 5) returns 30 but f(2*3*5) gives:

TypeError: f() takes exactly 3 arguments (1 given)

Please edit your question to add your code formatted in that way.

slelievre gravatar imageslelievre ( 4 years ago )

Here's the code. The most basic set intersection based on my research/reading:

sage: n=[some integer]; L=[f_1(x) for x in sxrange(1,(n+1)/2)]; M=[f_2(x) for x \
....:  in sxrange(1,(n+1)/2)]; [x for x in L if x in M]

For arbitrarily large n, this is too expensive from a time-complexity standpoint.

u220e gravatar imageu220e ( 4 years ago )

1 Answer

Sort by » oldest newest most voted
1

answered 4 years ago

slelievre gravatar image

updated 4 years ago

Reading about iterators

On the "Thematic tutorials" page of the SageMath documentation:

check out this tutorial:

Answer to the question

To recap, we start from

  • two integers n and m
  • two increasing functions
    • f:[1,...,n]mathbbR
    • g:[1,...,m]mathbbR

and we define

  • A = {f(i), i=1..n}
  • B = {g(i), i=1..m}

We know these sets have a single common point and we want to find it.

Our choice is between:

  • go upwards

    • start from the lowest elements of A and B
    • check if they are equal
      • if so we're done
      • if not take the next element from the set which had given us the lowest number
  • go upwards

    • start from the highest elements of A and B
    • check if they are equal
      • if so we're done
      • if not take the next element down from the set which had given us the highest number

Here is the upwards version:

def common_element_upwards(f, g, n, m):
    r"""
    Return the common element between `A = \{ f(i): i = 1 .. n \}`
    and `B = \{ g(i): i = 1 .. m \}`.

    Assumptions:

    - `f` and `g` are increasing functions
    - `A` and `B` have a common element
    """
    A = (f(i) for i in (1 .. n))
    B = (g(i) for i in (1 .. m))
    a = next(A)
    b = next(B)
    while a != b:
        if a < b:
            a = next(A)
        else:
            b = next(B)
    return a

Here is the downwards version:

def common_element_downwards(f, g, n, m):
    r"""
    Return a common element between the sets
    `A = \{ f(i): i = 1 .. n \}`
    and `B = \{ g(i): i = 1 .. m \}`.

    Assumptions:

    - `f` and `g` are increasing functions
    - `A` and `B` have a common element
    """
    A = (f(i) for i in (n, n - 1 .. 1))
    B = (g(i) for i in (m, m - 1 .. 1))
    a = next(A)
    b = next(B)
    while a != b:
        if a > b:
            a = next(A)
        else:
            b = next(B)
    return a

Example:

sage: f = lambda x: x^3 + 1
sage: g = lambda x: x^2
sage: n = 20
sage: m = 30
sage: common_element_upwards(f, g, n, m)
9
sage: common_element_downwards(f, g, n, m)
9
Preview: (hide)
link

Comments

Thanks. I've been through those tutorials, but I'll check them again in case I missed something. I've found "Computational Mathematics with SageMath" to be an excellent resource, but I'm still having trouble with the syntax of indices as they relate to iterative commands.

u220e gravatar imageu220e ( 4 years ago )

Fantastic...and not anything I've seen in the tutorials/literature, which means I would have been looking forever! I can't wait to try it and let you know how it goes. Thanks again.

u220e gravatar imageu220e ( 4 years ago )

Success! Now, I just need to find a way to program the index i to make it less expensive.

u220e gravatar imageu220e ( 4 years ago )

The "upwards" code works for very small n, but I keep getting a "StopIteration" error when using numbers even as small as four digits:

---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-259-34dce5deec42> in <module>()
----> 1 n=(Integer(5335)+Integer(1))/Integer(2); common_element_upwards(f, g, n, m)

<ipython-input-252-4f212b87ce54> in common_element_upwards(f, g, n, m)
     17           a = next(A)
     18         else:
---> 19           b = next(B)
     20     return a

StopIteration:
u220e gravatar imageu220e ( 4 years ago )

The StopIteration error happens when one of the sets runs out and no common element was found.

One could use a try/except to catch that and return a more meaningful error message in that case.

slelievre gravatar imageslelievre ( 4 years ago )

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 4 years ago

Seen: 761 times

Last updated: Sep 03 '20